Before this series began today, I felt a little scared. After all, the experts in the garden talked about the classic design patterns.ArticleThere are a lot of articles, especially those by Dr. Li huijun and Lu Zhenyu. Their text is like a breeze, and examples are lively and vivid. Fortunately, they all use C # To describe and do not provide necessary source code downloads. Therefore, I use C ++ here. First of all, I want to declare that my document is definitely not as good as they are, and the examples do not have their image, but I plan to put C ++'sCodeImplementation and class diagrams are provided to you, even as a supplement.
The design patterns naturally come up with several principles: I, open/closed rules (OCP), II, LSP, and III. Dependency inversion rules (DIP ); iv. Interface isolation rules (ISP); V, synthesis/aggregation reuse rules (CARP); vi and Demeter rules (SLS ), these rules are described in detail in the design mode (II) and design mode (III) of Mr Lu Zhenyu and are analyzed in a simple example. If you are interested, open the link and check it.
Note:
- The code here is implemented using the C ++ compiler of vs2005. Therefore, it cannot be ensured that compilation can be smoothly performed in other ides, but I think if you use other compilers, there should be no major problem, mainly the header file in stdafx. H files.
- The travel structure diagram is drawn using Microsoft's visio2003. After downloading it, you can use Visio to open it directly.
- In all future model examples, there will be customersProgramThe role of the customer program is not the content of the mode itself, it is outside the mode, but it is the customer program that has completed the use of the mode, the structure of the mode itself is the focus of the explanation, however, how to use the mode of the client program is also an important aspect of understanding the mode. Therefore, in my subsequent introduction, I will have the role of the client program, it also describes which roles in the call mode are used in the correct mode.
Simple factory model example
Eating is a basic requirement for humans. If humans do not need to eat, we may be able to live idle, so we do not need to work and study like we do today. We are studying to find a better job, a good job to earn more money, and finally to eat well and eat well. Therefore, it can be said that eating is closely related to people. Next we will introduce the factory model from the examples of eating.
If you want to eat, what should you do? Doing it yourself is equivalent to using new directly in the program. Of course, it's better for others to execute their own commands. Let's give the cooking task to your wife. Then she is a cooking factory. You tell her you want to eat braised pork, she will give you a dish of fragrant braised pork from the kitchen later. Let's have another steamed fish. There's not much big fish, so let's have another stir-fried spinach, and finally a tomato and egg soup. 1) It is the model of this problem.
(Figure 1)
Obviously, you are the client, and your wife is the factory. She has the method of cooking braised pork, the method of cooking steamed fish, and the method of doing stir-fried spinach and tomato and egg soup, the returned values of these methods are abstract food. Braised Pork, steamed fish, stir-fried spinach, tomato and eggs are the inheritance of food. Here you can eat and drink. The simple factory model has also taken shape. Haha, it's really nice to marry a good wife. It's delicious, delicious, and idle.
Next we will look at the analysis of the standard simple factory model.
Intention
Encapsulate the creation and encapsulation of a series of products with common features
Structure chart
(Figure 2)
Role Analysis
Product base : The base class of all products created by the factory. It describes the common public interfaces of all instances. It is used as the return parameter of the factory method.
Code implementation:
// --- Class product {protected: product (void); Public: Virtual ~ Product (void); Public: Virtual void function () = 0 ;}; // cppproduct: product (void) {}product ::~ Product (void ){}
Product: Product 1 and product 2. This role implements the interface defined by the abstract Product role.
Code implementation:
// Product Aclass concreteproducta: Public Product {public: concreteproducta (void); Public: Virtual ~ Concreteproducta (void); Public: Virtual void function () ;}; // cppconcreteproducta: concreteproducta () {cout <"Create a product" <Endl;} concreteproducta :: ~ Concreteproducta () {cout <"release a product" <Endl;} void concreteproducta: function () {cout <"this is the basic function of product A" <Endl ;}// product B is similar to product A and is not provided here. You can download the source code.
Factory: Responsible for the creation of specific products. There are two ways to create products. I. Different methods are used to create different products. II. The same method is used to create different products, then, you can create different products by passing parameters. The two modes are provided in this example. You can analyze them by yourself.
// Simple factory. This class does not need to be inherited. The generated product class simplefactory {public: simplefactory () {} public: ~ is directly hardcoded :~ Simplefactory () {} public: Product * createproduct (INT proucttype); product * createproducta (); product * createproductb () ;}; // cppproduct * simplefactory :: createproduct (INT producttype = 0) {product * p = 0; Switch (producttype) {Case 0: P = new concreteproducta (); break; Case 1: P = new concreteproductb (); break; default: P = new concreteproducta (); break;} return P;} product * simplefactory: createproducta () {return New concreteproducta ();} product * simplefactory: createproductb () {return New concreteproductb ();}
Client Program: The access role includes the product base class and factory class. Do not directly access the specific product category. The product function is called through the polymorphism of the base class pointer.
Access description: The customer program returns the abstract product by calling the factory method, and then executes the product method.
// Call the code simplefactory SF; product * P = SF. createproducta (); P-> function (); Delete P; P = SF. createproductb (); P-> function (); Delete P;
Advantages and disadvantages
Advantages: 1) solves a lot of new problems in the code first. To solve this problem, I want to summarize the benefits.
2) using the factory method to create an object inside a class is usually more flexible than creating an object directly.
Disadvantages: The modification is not closed. To add a new product, you must modify the factory. It violates the well-known open/closed rules (OCP ).
Additional instructions
- For more information, see the C # design mode (4) of Lu Zhenyu. The analysis shows two variants of the mode, which is simple to implement, if you are interested, you can use C ++ to implement it.
- In the code of the product base class, I used protected instead of public, mainly to reflect a minimum permission principle in encoding. This class is not allowed to be directly instantiated by users. Although the virtual void function () = 0 is used here, the compiler also controls that users are not allowed to instantiate directly, however, I still think that using private constructors to protect classes from direct instantiation is a good programming style.
Example of factory method mode:
People are the most greedy animals. If you want to eat back-to-pot meat, what should you do, so she added the method of cooking back-to-pot meat. If you want to eat a new dish later, you need to add a new method to your wife. Obviously, the disadvantages of cooking with her wife are exposed, the description of the program design means that the modifications cannot be closed. Of course, there are some advantages. If you have a wife in the factory, you don't need to cook these dishes by yourself. You just need to call the methods of the wife's factory directly.
In the face of the problem that the changes cannot be closed, is there a good solution? If you have money, the problem will be solved, and the wife will be abstracted into a base class. You will marry more specific wives, there are fish, vegetables, and stew wives respectively. If you want to eat a new dish, find a new woman and inherit from your wife's base class, let her cook the new dish. Obviously, there are a lot of wives. This is the dream of all men. There is no way, and the law does not allow them. So we just want to cook. The abstract class wife is not called a wife. It's called a cook, her child classes are naturally called Fish chefs and stew chefs. Now we can see that this pattern has changed. The structure has an abstract cook, and the abstract is not a specific processing product. As a result, the stew or stew is made, it is implemented by the inheritance subclass of this abstract factory. The current mode is changed to the factory method mode. The structure 1 above is changed to the structure of Figure 3 below.
(Figure 3)
Now let's analyze the current model. Obviously, the defects in the simple factory have been solved. To add a new dish, we only need to add a new cook. The original Cook is still doing the original work, in this way, your design is closed to the modification. You can see how perfect it is to release your wife and recruit a large number of chefs to your home. Your wife will love you too. The premise is that you need a lot of money. Of course, the amount of money here should be determined by the requirements of your customer's software investors in the software field.
The following describes the implementation of the standard factory model.
Intention
- Defines an interface for users to create objects, so that the subclass determines which class to instantiate. Factory method delays the instantiation of a class to its subclass.
- The above is the gof's intention to describe this mode. I would like to add that you can understand it as follows: To improve the problem that a simple factory cannot close the modification.
Structure
Figure 4
Role Analysis
Product base : The product base class of a simple factory is actually the same class as that of a simple factory. It is not rewritten here.
Product : It is also a specific product category of a simple factory. In order to reflect the closure of the modification, a new product category is added to the system, namely, "new product", which is called "concreteproductanew" in the code"
Factory Base : Defines the interface for the factory to create a product, but it is not implemented. The specific creation work is implemented by its inherited class.
Code instance
// Factory mode. The factory in this mode only defines the interface of the processing product, the specific generation is handed over to its inheritance class implementation // only the specific inheritance Class determines the product class factory to be processed {public: Factory (void); Public: Virtual ~ Factory (void); Public: Virtual Product * createproduct (INT producttype = 0) = 0 ;}; // cppfactory: Factory (void) {} Factory ::~ Factory (void ){}
Specific factory type: The specific implementation of the factory base class. This class decides to create a specific product. HereConcretefactory1ForFactory implementation,Concretefactory2ForNew Factory.
The following is the implementation code.
// The factory implements class concretefactory1: Public factory {public: concretefactory1 (); Public: Virtual ~ Concretefactory1 (); Public: Product * createproduct (INT producttype) ;}; // the new factory class concretefactory2: Public factory {public: concretefactory2 (); Public: Virtual ~ Concretefactory2 (); Public: Product * createproduct (INT producttype) ;}; // cppconcretefactory1: concretefactory1 () {} concretefactory1 ::~ Concretefactory1 () {} product * concretefactory1: createproduct (INT producttype = 0) {product * p = 0; Switch (producttype) {Case 0: P = new concreteproducta (); break; Case 1: P = new concreteproductb (); break; default: P = new concreteproducta (); break;} return P;} concretefactory2: concretefactory2 () {} concretefactory2: :~ Concretefactory2 () {}product * concretefactory2: createproduct (INT producttype = 0) {return New concreteproductanew ();}
Client call: Access role (product base class, factory base class, factory implementation class)
Call description: The customer program calls the factory implementation class through the factory base class method to create the desired product. This allows you to access product functions.
Code Implementation
Factory * FCT = new concretefactory1 (); product * P = FCT-> createproduct (0); P-> function (); Delete P; P = FCT-> createproduct (1); P-> function (); Delete P; Delete FCT; FCT = new concretefactory2 (); P = FCT-> createproduct (); delete P; Delete FCT;
Advantage and disadvantage Analysis
Advantages
- Advantages of a simple factory
- Solved the problem that the modification of a simple factory cannot be closed. Add a product to the system and add a product factory. This will not affect the abstract factory.
Disadvantages: Unable to create products of different series
Applicability
- When a class does not know the class of the object it must create.
- When a class wants its subclass to specify the object it creates.
- When a class delegates the responsibility of creating an object to one of multiple help sub-classes, and you want to localize the information of which help sub-classes are proxies.
Other references
- Lu Zhenyu's C # design pattern (5)-factory method pattern
- Terrylee's. Net Design Pattern (5): factory Method)
Example of abstract factory model life
The world is changing. Over time, there are more and more places to go through, and more friends are there. You have found that many dishes have been divided into different flavors, such as Lu, Cantonese, and Hunan, it is difficult for you to entertain different friends and use different cuisines. Your chefs are Lu cuisine. What should you do. Now let's go back to the simple factory model (that is, the model of cooking by our wife). We will inherit braised pork and produce braised pork in Lu cuisine, braised pork in Cantonese cuisine, and braised pork in Hunan cuisine; the steamed fish are inherited as the steamed fish of Lu cuisine, the steamed fish of Guangdong cuisine, and the steamed fish of Hunan cuisine, and so on. We also want to modify my wife's class so that she will not be able to return to the food base class. Instead, she will return to the braised pork, steamed fish, stir-fried spinach, tomato, and egg soup levels and abstract these methods, as the basis class of the cuisine factory, and then inherit from this base class, Lu Food Factory, Guangdong food factory, Hunan food factory and so on, and then create a specific dish in these specific factories, haha if you entertain Guangdong friends, you will use the Cantonese food factory and return a table of braised pork, steamed fish, spinach and tomato and egg soups for Cantonese cuisine. Your Guangdong friends will definitely have an appetite. Well, you have implemented the abstract factory model. The Structure Model diagram is also changed to 6.
(Figure 6)
Now we can see that it is perfect to hire a new cook to create a new dish, but don't be too happy, if you want to add a new dish, it will become very difficult.
Intention
Provides an interface for creating a series of related or mutually dependent objects without specifying their specific classes.
Structure
Role Analysis
Product base : This includes product base class A and product base class B. In my sample code, both products are inherited from the common base class, however, this inheritance relationship is beyond this model, and the model itself is concerned with the differences between the two product base classes.
Code implementation: the code here is the code implementation part of the specific product class in the simple factory mode borrowed. For your convenience, I will repeat it below.
// Product Aclass concreteproducta: Public Product {public: concreteproducta (void); Public: Virtual ~ Concreteproducta (void); Public: Virtual void function () ;}; // cppconcreteproducta: concreteproducta () {cout <"Create a product" <Endl;} concreteproducta :: ~ Concreteproducta () {cout <"release a product" <Endl;} void concreteproducta: function () {cout <"this is the basic function of product A" <Endl ;}// product B is similar to product A and is not provided here. You can download the source code.
Specific productsClass: the specific product categories here are products such as A1, A2, B1, and B2,
Code implementation: the corresponding implementation of A1 is ""
Class concreteproducta1: Public concreteproducta {public: concreteproducta1 (void); Public: Virtual ~ Concreteproducta1 (void); Public: Virtual void function () ;}; // cppconcreteproducta1: concreteproducta1 () {cout <"create A1 product" <Endl;} concreteproducta1 :: ~ Concreteproducta1 () {cout <"Release A1 product" <Endl;} void concreteproducta1: function () {cout <"basic functions of product A1" <Endl ;}
Factory AbstractionInterface: defines the interface for creating a product. The returned parameters are the common base classes of products A and B, the younger brother believes that this feature constitutes the difference between the abstract factory and the factory model.
Code Implementation
// Abstract Factory mode class abstractfactory {public: abstractfactory (); Public: Virtual ~ Abstractfactory (); Public: Virtual concreteproducta * createa () = 0; virtual concreteproductb * createb () = 0 ;}; // cpp?actfactory: abstractfactory () {} abstractfactory ::~ Abstractfactory (){}
Specific factory implementation classes: Factory 1 and factory 2. The new series only requires a new factory.
Code implementation: concreteabsfactory1 is used in factory 1. The Code of factory 2 is similar. The code is not provided here. You can see it in the download code.
/// Factory 1 ----- class concreteabsfactory1: Public abstractfactory {public: concreteabsfactory1 (); Public: Virtual ~ Concreteabsfactory1 (); Public: Virtual concreteproducta * createa (); Virtual concreteproductb * createb () ;}; // response: concreteabsfactory1 () {} concreteabsfactory1 ::~ Revoke () {} concreteproducta * concreteabsfactory1: createa () {return New concreteproducta1 ();} concreteproductb * concreteabsfactory1: createb () {return New concreteproductb1 ();}
Client Access: Access role (product base class, abstract factory, and specific factory implementation class)
Access Description: create a series of products by accessing the specific factory through the pointer of the abstract factory, and then access the product functions through the product base class pointer.
Call code:
Abstractfactory * absfct = new concreteabsfactory1 (); concreteproducta * CPA = absfct-> createa (); CPA-> function (); Delete CPA; concreteproductb * cardiopulmonary bypass = absfct-> createb (); cardiopulmonary bypass-> function (); Delete cardiopulmonary bypass; Delete absfct; absfct = new concreteabsfactory2 (); CPA = absfct-> createa (); CPA-> function (); Delete CPA; cardiopulmonary bypass = absfct-> createb (); cardiopulmonary bypass-> function (); Delete cardiopulmonary bypass;
Comparison with factory models
Now we can compare it with the factory model. The interface returned by the abstract factory is no longer a common base product of product A and product B, instead, product A and product B Base classes (in the factory model, they are specific implementation classes, which are changed to base classes. At this time, the factory abstraction is similar to the factory method in a simple factory, that is, these feature areas make them different from the factory model to the abstract factory model, therefore, the abstract factory solves the problem of creating a series of products with the same style (LU cuisine or Guangdong cuisine ), the factory method solution creates a series of products with common features (braised pork and steamed fish are all food ). Of course, the defects of the simple factory have appeared again in the abstract factory. If I want to add a new product, the abstract interface of the factory will change. Therefore, abstract factories are no more perfect than factory models, but they are different in their respective application fields. In fact, if the abstract factory mode interface is returned to the common base class of product A and product B (the parameter returned by the factory mode), you will find that this mode is so familiar with it, it does not just degrade into a factory model.
Differences between the class mode and the Object Mode: first, define the class "the mode uses the inheritance relationship to subclass the creation delay of the object, and the Object Mode delays the creation of the object to another object ". Analysis: first, they create objects not in the base class, they are all implemented in the subclass, so they all comply with the class mode concept; however, the creation of product objects in the factory mode is determined during the compilation period, and a fixed factory must be called, while the abstract factory mode dynamically determines the creation of products during the operation, the factory to be called is determined only at runtime, and the call factory changes with the running environment. (I am always confused here. You are welcome to discuss it)
Applicability
- A system must be independent of the creation, combination, and representation of its products.
- When a system needs to be configured by one of multiple product generations
- When you want to emphasize the design of a series of related product objects for joint use
- When you provide a product class library, instead of displaying their interfaces.
Reference
- Lu Zhenyu's C # design model (6)
- Terrylee's. Net Design Pattern (3): abstract factory pattern (Abstract Factory)