Patterns. Factory Method pattern. Implementation of the structure, the simplest case

Factory Method pattern. Implementation of the structure, the simplest case


Contents


Search others resources:

1. General information. The structure of the pattern. Figure

The Factory Method pattern is also called Virtual Constructor. This is a pattern that generates classes.

The pattern describes an interface for creating an object. In this case, the interface allows subclasses to decide what object to create.

The pattern should be applied in the following cases:

  • the class does not depend on the specific type of product being created;
  • the class does not know about the type of product to be created;
  • products to be created must or can be defined in derived classes.

The general structure of the Factory Method pattern is shown in Figure 1.

The structure of the FactoryMethod pattern

Figure 1. The structure of the Factory Method pattern

The participants of the pattern are:

  • Creator – abstract developer. Contains an abstract method for creating a product instance of the Product type;
  • ConcreteCreator – a specific developer. Implements a method for creating a product instance;
  • Product – interface, which is an abstract product. Serves to represent specific products;
  • ConcreteProduct – a specific product. Implements the Product interface of the abstract product;
  • Client – a client that calls the FactoryMethod() of the Creator to get a product instance.

The following links can be distinguished between the participants in the pattern:

  • the abstract class (interface) Creator defines the abstract method FactoryMethod(), which returns a reference to the Product;
  • the responsibility for creating a particular product lies with subclasses of the Creator class;
  • the ConcreteCreator class implements the FactoryMethod() method that creates a product – an object of the ConcreteProduct class.

 

2. Implementation of the Factory Method pattern. Program in C++

Below is the C++ code that implements the Factory Method pattern, the structure of which is shown in Figure 1.

#include <iostream>
using namespace std;

// ----------- Product classes ------------------------
// Abstract product
class Product abstract
{
public:
  virtual void Set(string) = 0;
  virtual string Get() abstract;

  // Some operations
  virtual void Operation() abstract;
};

// Concrete product
class ConcreteProduct : Product
{
private:
  string data;

public:
  // Constructor
  ConcreteProduct(string data = "") : data(data)
  { }

  // Access methods
  void Set(string data) { this->data = data; }
  string Get() { return data; }

  // Display internal state
  void Print(string msg)
  {
    cout << msg << " => " << data << endl;
  }

  // Implementation of the Operation() method
  void Operation() override
  {
    // display method name and data
    cout << "ConcreteProduct::Operation() => " << data << endl;
  }
};

// Abstract class Creator - abstract developer
class Creator abstract
{
public:
  virtual Product* FactoryMethod(string) abstract;
};

// Concrete Developer
class ConcreteCreator : Creator
{
public:
  // Product instance creation method
  Product* FactoryMethod(string data) override
  {
    // Some work
    return (Product*)new ConcreteProduct(data);
  }
};

void main()
{
  // The FactoryMethod pattern
  // Client code
  // Using the product
  Product* product = nullptr;

  // Create a product developer
  ConcreteCreator creator;

  // Get the product
  product = creator.FactoryMethod("Data of product.");

  // Call operations
  product->Operation();
  ((ConcreteProduct*)product)->Print("Product");

  if (product)
    delete product;
}

 

3. Results of using the pattern

For the Factory Method pattern, the following results can be defined.

1. The abstract class Creator depends on the specific type of products being created.

The responsibility for creating the product lies with the classes that inherit from the Creator class (implementing the Creator interface).

The benefit is that the Creator interface progressively refines specific products in their respective subclasses.

The downside is that when new product types are added, it becomes necessary to subclass the Creator class. This, in turn, can lead to unreasonable growth of subclasses.

2. The pattern combines two class hierarchies: product creators and products themselves.

3. It is possible to declare a default factory method.

In most cases, a factory method is abstract. This requires its mandatory implementation in inherited classes. If a factory method is defined with a default implementation, subclasses will only modify that method.

4. If the Creator class is implemented as a template class (Creator<T>), the product class can be passed as a type parameter T. In this case, the factory method will create objects of the generic type parameter T and it is not necessary to use inheritance when defining a new product type.

 

4. Advantages and disadvantages of the pattern

The advantages of the Factory Method pattern include the following.

  1. The client does not need to pay much attention to configuring a specific creator instance (ConcreteCreator) by a specific product.
  2. Each product (ConcreteProduct) can be configured with parameters that only a specific creator (ConcreteCreator) knows about.
  3. The client interacts with concrete creators (ConcreteCreator) through an abstract creator (Creator). Thus, the client has information only about the abstract creator.

The disadvantage of the pattern is that the product type (ConcreteProduct) for a specific creator class (ConcreteCreator) is determined at compile time (statically) and can be changed at run time.

 


Related topics