Design Patterns (2): Abstract Factory Patterns
Definition:
· Provides an interface for creating a series of related or interdependent objects that only need to know the series of objects, not the specific objects.
· In the abstract factory pattern, interfaces are responsible for creating factories for related objects without explicitly specifying their classes. Each generated factory can provide objects according to the factory pattern.
The main solutions are:
· Interface selection.
When to use:
· There are more than one product family in the system, and the system consumes only one of them.
Take code as an example:
The class diagram is as follows
According to the class diagram:
First, create two product families, product A and product B.
class ProductA//Product A { public: virtual ~ProductA() {} virtual const char* getName() = 0; // ... }; class ProductB//Product B { public: virtual ~ProductB() {} virtual const char* getName() = 0; // ... };
2. Create case class product grades X and Y of product A and product B respectively
class ConcreteProductAX : public ProductA//Product AX { public: ~ConcreteProductAX() {} const char* getName() { return "A-X"; } // ... }; class ConcreteProductAY : public ProductA//Product AY { public: ~ConcreteProductAY() {} const char* getName() { return "A-Y"; } // ... }; class ConcreteProductBX : public ProductB//Product BX { public: ~ConcreteProductBX() {} const char* getName() { return "B-X"; } // ... }; class ConcreteProductBY : public ProductB//Product BY { public: ~ConcreteProductBY() {} const char* getName() { return "B-Y"; } // ... };
Creating abstract factory classes
class AbstractFactory { public: virtual ~AbstractFactory() {} virtual ProductA *createProductA() = 0;//Pure Virtual Function Declaring Creation Product A virtual ProductB *createProductB() = 0;//Pure virtual functions declaring the creation of product B };
Here, the two purely virtual functions declared are the most important in the abstract factory class.
4. Create instance abstract factory class
class ConcreteFactoryX : public AbstractFactory { public: ~ConcreteFactoryX() {} ProductA *createProductA() { return new ConcreteProductAX(); } ProductB *createProductB() { return new ConcreteProductBX(); } // ... }; class ConcreteFactoryY : public AbstractFactory { public: ~ConcreteFactoryY() {} ProductA *createProductA() { return new ConcreteProductAY(); } ProductB *createProductB() { return new ConcreteProductBY(); } // ... };
Factory X and Y are declared here to produce X and Y products corresponding to A and B, respectively.
5. Calling with main function
int main() { ConcreteFactoryX *factoryX = new ConcreteFactoryX(); ConcreteFactoryY *factoryY = new ConcreteFactoryY(); ProductA *p1 = factoryX->createProductA(); std::cout << "Product: " << p1->getName() << std::endl; ProductA *p2 = factoryY->createProductA(); std::cout << "Product: " << p2->getName() << std::endl; delete p1; delete p2; delete factoryX; delete factoryY; return 0; }
This implements a simple abstract factory pattern
Advantages and disadvantages of abstract factory pattern:
Advantages: When multiple objects in a product family are designed to work together, it ensures that clients always use only objects in the same product family.
Disadvantage: Product family expansion is very difficult, to add a series of products, both in the abstract Creator add code, but also in the specific code.
ctoryY;
return 0;
}
This implements a simple abstract factory pattern Advantages and disadvantages of abstract factory pattern: Advantages **: When multiple objects in a product family are designed to work together, it ensures that clients always use only objects in the same product family. ** Disadvantage **: It is very difficult to extend the product family. To add a series of products, we need to add code not only in the abstract Creator, but also in the concrete. ** Notes: ** Product family is difficult to expand and product grade is easy to expand.