Opening part-Introduction to models and principles
I have been in contact with the design model for nearly two years. I have been trying to write something to consolidate my learning, but I have never been able to do anything. I always want to write more time and knowledge, however, the longer it takes, the more time it feels that there will never be a proper time. Only continuous practice can be used for improvement. Maybe I will never be able to write it again, so I finally started.
When talking about the design model, no one should be able to go beyond gof's work, so there is no innovation. In the end, we should repeat the discussions and ideas of our predecessors, it is more about organization and personal experience. Since the birth of the design model, the industry has undergone great changes, and many development tools and processes have been updated many times. Therefore, many models are not very commonly used now, this plan focuses only on the most popular models and will gradually supplement other models in the future. (See the outline below)
This series of plans is based on the structure of head first design patterns. It can also be called the study notes of this book, but it is more about the gradual explanation of the original book, we strive to join in more personal thoughts and opinions, hoping that they will eventually resonate with everyone.
Several heroes and their predecessors have already written articles on the Design Pattern series in the garden. I have absorbed too many excellent articles from them. I would like to thank you again.
Outline
The following is the first draft of this series. In the future, we will add or delete the series based on actual conditions.
Opening part-modes and principles
1. Duck-policy Mode
2. Weather Station story-Observer Model
3. Coffee Cup-modifier Mode
4. Delicious Pisa-factory Model
5. Chocolate-single-piece Mode
6. Remote control-command mode
7. Family theatre-adapter and facade Mode
8. Hollywood principles-template method mode
9. restaurant menu-iterator and merging mode
10. Candy machine-status Mode
11. Chief Representative-Agent Mode
12. Duplicate duck out of the river-compound use mode
13. Thinking in patterns-getting along with patterns
14. Remaining Modes
Design Mode Introduction
Mode: each mode describes a problem that occurs repeatedly around us and the core of the solution to the problem.
This is the most classic definition of patterns, written by the architect Christopher Alexander. If this is the first time you see this sentence, most people will feel abstract and difficult to understand. In fact, the word "Mode" is just a codename, just like my name is Justin. If I change my name to Tom, it's okay, but I prefer the name of Justin, so from Christopher, with the word "pattern", people also refer to the description and solution of "repeated problems" as pattern.
The term "Mode" is not limited to the software development industry. It is almost everywhere. It is actually an accumulation of experience, just as most people's educational experience is from elementary school to junior high school to university, this is also a model of education in China. Nowadays, it is becoming increasingly popular, it is also another overseas study mode. The 23 classic design patterns described in gof's design patterns: the basis for reusable object-oriented software laid the foundation for the software industry, since then, people have mentioned that the "Design Model" refers to the "Object-Oriented Design Model". However, as mentioned above, the model is definitely not limited to the software industry, even in the software industry, it is not limited to the 23 design patterns described by gof, such as the most famous Martin
Flower's enterprise architecture model also includes common MVC and IOC.
[Speaking of this, it is necessary to declare that, in this series of articles, all models mentioned refer to the gof-based Design Model of the software industry: the object-oriented design mode in the document "reusable basics of object-oriented software", except for the GRASP mode.]
Because the mode is an accumulation and summarization of experience, we can stand on the shoulders of giants to think about and solve problems. Skilled use of the design mode can improve our work efficiency, improve product quality and ultimately bring economic benefits. Therefore, any individual or group that wants to develop flexible, efficient, and robust software products must master and correctly use the design model.
So let's get started ......
More important than the design model: grasp (Responsibility Assignment principle)
To learn the design pattern, we must first know some basic knowledge. The design pattern is an efficient and flexible way to use classes and objects. That is to say, only when there are classes and objects can we have a place to use the design model. Otherwise, everything is empty talk, so what about classes and objects? In this case, the GRASP model, which is more important than the 23 design modes, is now available. Hey hey, this is the boss!
GRASP (General Responsibility Assignment Software patterns) is called "General Responsibility Assignment software model" in Chinese. Grasp consists of nine modes, which describe the basic principles of Object Design and Responsibility Assignment. That is to say, how to abstract the business functions of the real world into objects, how to determine the number of objects in a system, and what responsibilities each object includes, the GRASP mode provides the most basic guiding principles. Beginners should master and understand these principles as soon as possible, because this is the basis for designing an object-oriented system.It can be said that grasp is the basis for learning to use design patterns.
1. Information expert)
The information expert model is the most basic principle of object-oriented design. It is the most commonly used principle that should be integrated with our ideas. That is to say, when we design an object (class), if a class has all the information required to complete a specific responsibility, this responsibility should be assigned to this class for implementation. At this time, this class is the information expert relative to this responsibility.
For example: The shopping cart (shopcar) in a common online store needs to make each item (SKU) appear only once in the shopping cart. To buy the same item, you only need to update the quantity of items. For example:
To solve this problem, we need to weigh whether the same methods of products need to be put into the class for implementation? The analysis business knows that the product must be uniquely identified by the product number (skuid), and the product number is unique in the product class. Therefore, according to the information expert model, whether the methods for comparing commodities are the same should be put in the commodity class.
2. creator (creator)
In practice, Class A should be used to create Class B when any of the following conditions are met. At this time, a is the creator of Class B:
A. A is the aggregation of B.
B. A is the container of B.
C. A holds the information of initializing B (data)
D. A record B's instance
E. A frequent use of B
If one class creates another class, the two classes are coupled and can be said to have dependencies. There is no error in dependency or coupling, but the problems they bring about are that they will generate a chain reaction in future maintenance, and the necessary coupling cannot be escaped, what we can do is to correctly create Coupling Relationships and do not randomly establish dependencies between classes. What should we do? It is necessary to abide by the basic principles stipulated by the Creator mode. If the above conditions are not met, a cannot be used to create B.
For example: Because order is the container of a commodity (SKU), the order should be used to create a commodity. For example:
This is because the order is the container of the product and only the information of the initial product is held by the order. Therefore, this coupling relationship is correct and cannot be avoided. Therefore, the order is used to create the product.
3. Low coupling (low coupling)
The low coupling mode means we need to minimize the connections between classes.
Its role is very important:
A. Low coupling reduces the impact on other classes due to changes in one class.
B. Low coupling makes the class easier to understand, because the class will become simpler and more cohesive.
The following situations may cause coupling between Class A and Class B:
A. A is the property of B.
B. A method for calling B's instance
The C. A method references B. For example, B is the return value or parameter of method.
D. A is a subclass of B, or a implements B
There are also some basic principles for low coupling:
A. Don't talk to strangers principles:
That is to say, do not make unnecessary connections between two objects that do not need to communicate. If the connection is established, problems may occur. If it is not connected, it will be a hundred times!
B. If a is connected to B, and B is not assigned the responsibility of A (in violation of the information expert model), B is assigned the responsibility of B.
C. Internal classes of two different modules cannot be directly connected; otherwise, you will be rewarded! Hey!
For example: In the example of the Creator model, another shipping person is required to check the goods (SKU) on the order and calculate the total price of the goods, however, because the coupling between orders and commodities already exists, assigning this responsibility to orders is more appropriate, which can reduce coupling and reduce system complexity. For example:
Here we add a totalprice () method to the order class to calculate the total price without adding unnecessary coupling.
4. High Cohesion (High Cohesion)
High Cohesion means assigning cohesion responsibilities to classes as much as possible. It can also be said to be functional cohesion responsibilities. That is, the function is closely related to the responsibilities should be put in a class, and the limited functions should be completed together, that is, high internal aggregation. This is more conducive to class understanding and reuse, and also facilitates class maintenance.
High cohesion can also be said to be an isolation. The human body is composed of many independent cells. The building consists of many bricks, steel bars, and concrete. Each part (class) each part has its own independent responsibilities and features. If a problem occurs in each part, it will not affect other parts, because highly cohesive objects are isolated.
For example: An order Data Access class (orderdao) can be saved as an Excel mode or saved to a database. Therefore, different responsibilities are best achieved by different classes, this is the design of high cohesion, such:
Here, we put two different data storage functions in two classes to implement them. In this way, if an error occurs in the function of saving data to excel in the future, check the orderdaoexcel class, this also makes the system more modular and easier to divide tasks. For example, these two classes can assign different persons for simultaneous development, which also improves the team collaboration and development progress.
5. Controller)
The responsibility for receiving and processing system events should generally be assigned to a class that can represent the entire system, such classes are usually named "XX processor", "XX coordinator", or "XX session ".
The following principles apply to the Controller class:
A. the receiving and processing of system events are usually replaced by an advanced class.
B. A sub-system has many controller classes to process different transactions respectively.
For more details about this mode, see chapter 16th of UML and mode application.
6. polymorphism (polymorphism)
Polymorphism here is the same as "polymorphism", one of the three basic features of OO.
For example: We want to design a drawing program. To support drawing different types of images, we define an abstract class shape, rectangle (rectangle), and circle (round) to inherit this abstract class respectively, and overwrite the draw () method in the shape class, so that we can use the same interface (shape abstract class) to draw different graphics, such:
This design is more in line with the principles of high cohesion and low coupling. Although we have added a diamond class, it has no impact on the entire system structure, you only need to add a class that inherits the shape.
7. pure fabrication (purely fictitious)
The pure fiction here is similar to the pure fiction function we often call. High Cohesion and low coupling are the ultimate goal of system design, but cohesion and coupling are always contradictory. High Cohesion thinks that this splits more classes, but objects need to collaborate to complete the task, which in turn leads to high coupling. How can we solve this contradiction? In this case, we need to use a purely fictitious class to coordinate cohesion and coupling, which can solve the above problem to a certain extent.
For example: In the example of the above multi-state mode, if our plotting program needs to support different systems, the drawing function also needs different implementation methods because the API structure of different systems is different, so how should we design it more appropriately? For example:
Here we can see that the pure imaginary class abstractshape is added, and no system can draw images through the abstractshape class. We didn't reduce the original cohesion or increase too many coupling, it can be both fish and bear's paw. Hahaha!
8. indirection (indirect)
As the name implies, "indirect" means that this task cannot be handled directly, and you need to make a detour. The benefit of turning around is that objects that are directly connected together are isolated from each other, and one change will not affect the other. Just as I said in the previous low coupling mode, "Internal classes of two different modules cannot be directly connected", but we can indirectly connect two different modules through intermediate classes, in this way, there is still no coupling/dependency between the two modules.
9. Protected variations (protected changes)
Locate unstable changes in advance and encapsulate them with a unified interface. If future changes occur, you can use the interface to expand new functions without modifying the original implementation. This mode can also be understood as the OCP principle, that is to say, a software entity should be responsible for extension development, and the modification should be disabled. When designing a module, make sure that the module can be expanded without being modified. The advantage of doing so is to provide new responsibilities to the system through expansion to meet new requirements without changing the original functions of the system. The OCP principles will be discussed separately later.
More important than design patterns: Design Principles
We live in a world full of Rules. Under the complex and changing appearance, everything is governed by the eternal truth and operates regularly. The same is true for patterns. Whatever the patterns, there are some "eternal truths" hidden behind them. This truth is the design principle. I remember when I attended an architect training at Microsoft and talked about the design model, someone asked the teacher a question: "What is more important than the design model ?", The teacher is a developer with many years of practical experience. He did not hesitate to say, "What is more important than model is principle ". I often think of this sentence as a great answer. Indeed, what is more important than principles? Just like people's world outlook and outlook on life, it is the root of all your actions. For design patterns, why does this pattern solve this problem like this, and for other models, they all follow the principle of eternal design.It can be said that the design principle is the soul of the design model.
I have not discussed the design principles in depth yet. I suggest you go to agile software development-principles, models, and practices. Here is a simple explanation of some common design principles:
1. Single Responsibility Principle (SRP)
"For a class, there should be only one reason for its change ." That is to say, do not put different responsibilities for different reasons of change together, because different changes will affect irrelevant responsibilities. In other words, you don't need to worry about things you shouldn't care about. You can manage your own things, and your own things hurt others. (Of course, we have two different things to do here, and we advocate "yes" and "yes !)
For example: For the design in reference, the graphic computing program only uses the square area () method and never uses the draw () method, but is associated with the draw method. This violates the single principle. If the draw () method changes due to the graphic plotting program in the future, it will affect the graphic computing program that is unrelated to it.
So what should we do? For example, assign different responsibilities to different classes so that the responsibilities of a single class are as single as possible, and changes are isolated so that they will not affect each other.
2. Open-Close principle (OCP)
"Software entities (classes, modules, functions, etc.) should be extensible, but cannot be modified ." Hey! What a plain word, I was dumb when I first read this principle. I was thinking, "Isn't this a & # % daydream! How can I extend it without modifying it ?" However, as I learned more deeply, I understood what this "Don't modify" means. It means "you can add new classes at will, but don't modify the original classes ". It is much better to understand from this perspective. In fact, it is still a problem of isolation and change.
For example: For example, a client program uses the data access interface to operate data. For this system, the SQL server or Oracle database is planned to be used at the beginning, but later the cost is taken into account, use a free MySQL database. For the client program, subsequent data expansion has no impact on it, and it uses a free and easy-to-use MySQL database without knowing it, thanks to the OCP principles.
3. Dependency inversion principle (DIP)
"Abstraction should not depend on details. Details should depend on abstraction ." There is another saying about this principle: "The top layer should not depend on the bottom layer, and both should depend on abstraction ." In fact, they are all right. The key is to understand that only abstract things are the most stable. That is to say, we rely on its stability. If the "abstraction" is unstable in the future, who will stabilize me and who will I talk about? Isn't it just a big deal! Haha!
For example: For the design reference, a switch is directly connected with the lamp. That is to say, the switch depends on the method of opening and closing the lamp. If I want to use this switch, I can also turn on other things, such as TV and audio. Obviously, this design cannot satisfy this requirement, because we rely on details rather than abstraction, and this switch is equivalent to "Lamp Switch ".
So how should we design a general switch? Refer to the design. OK! Now we can not only turn on the light, but also turn on the TV and audio, and even anything that implements the "switch interface" in the future.
4. Interface isolation principle (ISP)
"Customers should not be forced to rely on methods they do not need. An interface belongs to a customer and does not belong to its class hierarchy ." This is quite clear. In other words, do not force customers to use the methods they do not use. If you force users to use the methods they do not use, then these customers will face the changes caused by the changes to these unused methods.
For example: Reference design: In this design, withdrawals, deposits, and transfers all use a common interface, that is, each class is forced to rely on the interface methods of the other two classes, therefore, each class may be affected by the methods of the other two classes (not related to itself. For withdrawal, it does not care about "deposit operations" or "transfer operations", but it is affected by the changes in these two methods !!!
So how can we solve this problem? For reference design, a dedicated operation interface is designed for each class so that they only depend on the methods of their relationship, so that they will not affect each other and will not happen to others!
5. replacement principle (LSP)
"Child types must be able to replace their base types ." That is to say, the "is a" relationship in the inheritance must be guaranteed. Otherwise, what is the inheritance! If the LSP principle is violated, the type determination at runtime (rtti) often violates the OCP principle.
For example, the parameter of function a is of the base type, and the object passed during the call is of the Child type. Normally, adding a child type does not affect function A. If LSP is violated, function A must be careful when determining the specific type passed in. Otherwise, an error will occur, which violates the OCP principle.
About model learning
Understanding object-oriented is the basis for learning the design model well. Only by mastering certain object-oriented design principles can we master the essence of the object-oriented design model, so as to flexibly use the design model. Knowing only the language mechanism of OO is not enough. Knowing the encapsulation, inheritance, and polymorphism in the language only meets the most basic conditions and must truly play the powerful role of OO, the key is to have a deep understanding of the above grasp mode and design principles. On this basis, we should have a deep understanding of the design mode and continue to hone it in practice.
The pattern is less important than the OO principle. If you can design a program that basically complies with the above principles, you may have summarized a new pattern, therefore, the learning model aims to deeply understand oo ideas and principles, so that we can write high cohesion and low coupling programs.
In addition, when I recently studied the "C # object-oriented design model outline series of courses" by Mr. Li Jianzhong, I proposed a "restructuring to the model" theory, which makes sense, the pattern is not entirely a template for us to apply. In a specific business environment, we may only implement the design pattern similar to the XX pattern, because for this environment, such use is the most appropriate, rather than when it is necessary to completely copy the format of gof's 23 design patterns. The patterns are dead, while people are active, find the most appropriate implementation method and do not use the design mode for the design mode.