This part of the content excerpt from Https://www.cnblogs.com/dolphin0520/p/3919839.html, added to their own understanding; I. Single RESPONSIBILITY principle
Original link: http://blog.csdn.net/lovelion/article/details/7536542
The single responsibility principle is the simplest object-oriented design principle, which is used to control the granularity of a class. The single responsibility principle is defined as follows:
Single Responsibility Principle, SRP): Popular is a class is the same as a man more specificity, the more exclusive and other girls stir less, coupled less ;
A class is responsible only for the corresponding responsibilities in a functional area, or can be defined as: For a class, there should be only one cause for it to change.
The principle of single responsibility is to achieve high cohesion, low-coupling guidelines, it is the simplest but most difficult to apply the principle, the need for designers to discover the different responsibilities of the class and separate it, and the discovery of multiple responsibilities of the class requires designers have strong analytical design capabilities and relevant practical experience. Single duty principle tells us: A class can not be too "tired"! In a software system, the more responsibilities a class (large to a module, small to a method) assumes, the less likely it is to be reused , and the more responsibilities a class assumes, the equivalent of coupling those responsibilities together, which, when one of the responsibilities changes, may affect the operation of other duties, So to separate these responsibilities, encapsulate different responsibilities in different classes, encapsulate different causes of change in different classes, and encapsulate them in the same class if multiple responsibilities are always changed at the same time.
The following is a simple example to further analyze the single responsibility principle:
Sunny software company Developers for a CRM (Customer relationship Management, CRM) system of Customer information graphical statistical module presented 1 initial design scheme:
Figure 1 Schematic diagram of the initial design scheme
In Figure 1, the methods in the Customerdatachart class are described as follows: the Getconnection () method is used to connect to the database, Findcustomers () is used to query all customer information, Createchart () is used to create the chart, Displaychart () is used to display the chart.
A single responsibility principle is now used to reconstruct it.
(1) Dbutil: Responsible for connecting the database, including the database connection method getconnection (); In Figure 1, the Customerdatachart class takes on too many responsibilities, including both database-related methods and methods related to chart generation and display. If you also need to connect to a database in other classes or use the Findcustomers () method to query the customer information, it is difficult to implement code reuse. Whether you modify a database connection or change the way the chart is displayed, you need to modify the class, which is more than one cause of its change, and violates the principle of single responsibility. It is therefore necessary to split the class so that it meets a single duty principle, and class Customerdatachart can be split into the following three classes:
(2) Customerdao: Responsible for operating the Customer table in the database, including the Customer table additions and deletions and other methods, such as findcustomers ();
(3) Customerdatachart: Responsible for chart generation and display, including methods Createchart () and Displaychart ().
The refactoring with the single responsibility principle is shown in structure 2:
Fig. 2 Structure diagram after reconstruction
Two. Opening and closing principle
Original link: http://blog.csdn.net/lovelion/article/details/7537584
The opening and closing principle is the first cornerstone of object-oriented reusable design, and it is the most important object-oriented design principle. The opening and closing principle was proposed by Bertrand Meyer in 1988 and is defined as follows:
Opening and closing principle (open-closed Principle, OCP): A software entity should open for expansion and close for modifications. That is, the software entity should try to extend without modifying the original code. the popular saying is that once I write a block of code, do not re-operate it, if the modification introduced the problem, is a very serious problem ;
Any software needs to face a very important problem, that is, their needs will change over time. When the software system needs to face the new requirements, we should try to ensure that the system design framework is stable. If a software design conforms to the open and close principle, it is very convenient to extend the system, and without modifying the existing code in the extension, the software system has the adaptability and flexibility to have good stability and continuity. With the increasing of software scale, the longer life of software and the higher cost of software maintenance, it becomes more and more important to design a software system that satisfies the opening and shutting principle. In the definition of open and closed principle, a software entity can refer to a software module, a local structure consisting of multiple classes, or a separate class .
in order to satisfy the principle of opening and closing, abstract design is needed for the system, and abstraction is the key to open and close principle. in programming languages such as Java, C #, you can define a relatively stable abstraction layer for the system, and move the different implementation behaviors to the specific implementation layer. in many object-oriented programming languages, interfaces, abstract classes and other mechanisms can be used to define the abstraction layer of the system, and then extend it through specific classes (which can be understood as polymorphic mechanisms) , and if you need to modify the behavior of the system without any changes to the abstraction layer, Only need to add new concrete class to realize new business function, realize the function of extending system without modifying existing code, and meet the requirement of opening and shutting principle.
The CRM system developed by Sunny software companies can display various types of charts, such as pie charts and histograms, in order to support a variety of chart display methods, as shown in the original design Scenario 1:
Figure 1 Schematic diagram of the initial design scheme
The following code fragment exists in the display () method of the Chartdisplay class
if (Type.equals ("pie")) { new piechart (); Chart.display ();} Else if (Type.equals ("Bar")) { new barchart (); Chart.display ();}
In this code, if you need to add a new chart class, such as a line chart Linechart, you need to modify the source code of the display () method of the Chartdisplay class, add new judgment logic, and violate the open and closed principle.
The system is reconstructed to conform to the opening and shutting principle.
(1) Add an abstract chart class Abstractchart, the various specific chart classes as their subclasses; In this example, because the display () method of the Chartdisplay class is programmed for each chart class, adding a new chart class has to modify the source code. The system can be reconstructed in an abstract way to add new chart classes without modifying the source code and meeting the open and closed principle. The following are the specific practices:
(2) The Chartdisplay class is programmed for abstract chart classes, and the client determines which specific chart to use.
After refactoring, structure 2 shows:
Fig. 2 Structure diagram after reconstruction
In Figure 2, we introduced the abstract chart class Abstractchart, and Chartdisplay for the abstract chart class, and the Setchart () method is set by the client to instantiate the specific chart object, in the Chartdisplay display () The display () method in the call chart object in the method displays the chart. If you need to add a new chart, such as a line chart Linechart, you just need to add linechart as a subclass of Abstractchart, and inject a Linechart object into the Chartdisplay on the client without modifying the source code of the existing class library.
Note: Because the XML and properties format configuration file is a plain text file, can be edited directly through the VI editor or Notepad, and do not need to compile, so in software development, the configuration file is generally not modified as the system source code modification. If a system only involves modifying the configuration file when it is extended, and the original Java code or C # code does not make any changes, the system can be considered as a system that conforms to the open and closed principle.
Three. The Richter replacement principle
Original link: http://blog.csdn.net/lovelion/article/details/7540445
The Richter substitution principle was presented in 1994 by the 2008 Turing Award winner, Professor Barbara Liskov , the first woman in computer science in the United States and Professor Jeannette Wing of Carnegie Mellon University. It is strictly stated as follows: If for each object of type S O1, there is an object of type T O2, so that all program P defined in T O1 the substitution O2 of all objects, the behavior of the program P does not change, then the type S is a subtype of type T. This definition is rather awkward and difficult to understand, so we generally use another popular version of it:
Richter substitution principle (Liskov Substitution Principle, LSP): All references to base class (parent class) must be able to transparently use objects of its subclasses, simple Can be understood as the subclass and the parent class method has been the premise or the parent class does not call the subclass of the unique method, where the use of subclasses with the parent class to completely replace the use, to implement the extension;
For example, there are two classes, One class is BaseClass, the other is the subclass class, and the subclass class is a subclass of the BaseClass class, so if a method can accept base class object base of a baseclass type, such as: Method1 (Base), Then it is bound to accept a subclass object of type BaseClass sub,method1 (sub) to function properly. Conversely, substitution is not tenable, such as a method Method2 accepts a subclass object of type BaseClass as a parameter: Method2 (sub), then generally there is no method2 (base), unless it is an overloaded method. The principle of substitution of the Richter scale tells us that Replace a base class object in the software with its subclass object, the program will not produce any errors and exceptions, and conversely, if a software entity uses a subclass object, then it is not necessarily able to use the base class object. For example: I like animals, I must like dogs, because dogs are the children of animals, but I like dogs, can not be concluded that I like animals, because I do not like mice, although it is also an animal.
The principle of substitution of the Richter scale is one of the important ways to realize the open and closed principle, because the subclass object can be used wherever the base class object is used, so as far as possible the base class type is used in the program to define the object, while at run time the subclass type is determined, and the child class object is substituted for the parent class object.
There are several issues to be aware of when using the Richter substitution principle:
(1) All methods of a subclass must be declared in the parent class, or the child class must implement all methods declared in the parent class. According to the principle of the substitution of the Richter scale, in order to ensure the extensibility of the system, the parent class is usually used in the program to define, if a method exists only in the subclass, does not provide the corresponding declaration in the parent class, the method cannot be used in the object defined in the parent class.
(2) When we use the Richter substitution principle, we try to design the parent class as abstract class or interface, let the subclass inherit the parent class or implement the parent interface, and implement the method declared in the parent class, run, the subclass instance replaces the parent class instance, we can extend the function of the system conveniently . Without modifying the code of the original subclass, adding new functionality can be achieved by adding a new subclass. The principle of substitution on the Richter scale is one of the concrete means of realization.
(3) In the Java language, during the compilation phase, the Java compiler checks whether a program conforms to the Richter substitution principle, which is an implementation-independent, purely syntactic check, but the Java compiler's check is limited.
In the CRM system developed by Sunny software company, customers can be divided into VIP customers (Vipcustomer) and ordinary Customers (Commoncustomer), the system needs to provide a function of sending email, as shown in the original design scheme 1:
Figure 1 Original structure diagram After further analysis of the system, it was found that the process of sending mail was the same for both ordinary customers and VIP customers, meaning that the code in the two Send () methods was duplicated, and that new types of customers would be added to the system. To make the system more scalable, and to reduce code duplication, it is reconstructed using the Richter substitution principle. |
In this example, you can consider adding a new abstract customer class customer, and the Commoncustomer and Vipcustomer classes as their subclasses, the message sending class Emailsender class for the abstract customer class customer programming, according to the principle of the Richter substitution, The place where the base class object can be accepted is bound to accept the subclass object, so the parameter type of the Send () method in Emailsender is changed to customer, and if you need to add a new type of customer, just use it as a subclass of the customer class. The reconstructed structure is shown in 2:
Fig. 2 Structure diagram after reconstruction
the principle of substitution on the Richter scale is one of the important ways to realize open closed principle. In this example, you use the base class object when passing parameters, and in addition, you can use the Richter substitution principle when defining member variables, defining local variables, and determining method return types. For the base class programming, determine the specific subclass when the program runs.
Add a blog post on the Richter replacement principle:
http://blog.csdn.net/zhengzhb/article/details/7281833
Four. Dependency inversion principle
Original link: http://blog.csdn.net/lovelion/article/details/7562783
If the principle of open-end is object-oriented design, then the dependency reversal principle is one of the main implementation mechanisms of object-oriented design, which is the concrete implementation of system abstraction. The dependency reversal principle was Robert c. Martin 's 1996 column for "C++reporter", Engineering notebook's third, which he later added to his 2002 classic "Agile Software development, principles, Patterns, and Practices"in a book. The dependency reversal principle is defined as follows:
dependency reversal principle (Dependency inversion Principle, DIP): Abstract should not be dependent on details, details should be dependent on abstraction. In other words, you want to program for the interface, not for the implementation. You can use high-level interfaces as much as possible in the delivery of specific classes, increase extensibility, or you can understand that the name of the child is not written where the head of the family can be written;
After the abstraction layer is introduced, the system will have the flexibility to programmatically use the abstraction layer in the program and write the specific class in the configuration file, If the system behavior changes, only need to extend the abstraction layer, and modify the configuration file, without modifying the original system source code, in the case of non-modification to expand the system's function, to meet the requirements of the open-close principle. according to Lai reverse principle requires us to pass parameters in the program code or in association relations, as far as possible to refer to the high level of the abstract layer class, that is, using interfaces and abstract classes for variable type declaration, parameter type declaration, method return type declaration, and data type conversion, and do not use specific classes to do these things. to ensure the application of this principle, a concrete class should implement only the methods declared in the interface or abstract class, and not the redundant methods, otherwise you will not be able to invoke the new method added to the subclass.
In implementing the dependency reversal principle, we need to program for the abstraction layer and inject the object of the specific class into other objects through dependency injection (dependencyinjection, DI) , which refers to when an object has to be dependent on another object To inject the objects that depend on them through abstraction . There are three common injection methods, namely: construction Injection, value injection (setter injection) and interface injection . Construct injection refers to the object that passes through the constructor to the concrete class, and the value injection refers to the object that passes through the setter method to the concrete class, and interface injection refers to the object of the concrete class through the business method declared in the interface. These methods use abstract types when they are defined, and then pass through the object of a specific type at run time, overriding the parent class object by a subclass object.
The following is a simple example to deepen the understanding of the dependency reversal principle:
Sunny software Developers in the development of a CRM system found that: the system often needs to store the TXT or Excel files stored in the customer information into the database, so the need for data format conversion. The method of invoking the data Format transformation class in the customer data manipulation class implements the format conversion and the database insert operation, as shown in the initial design scheme structure 1: Figure 1 Initial design scheme structure When coding the structure shown in Figure 1, the sunny software company developer found a very serious problem with the design Since the data source is not necessarily the same every time you convert data, you need to change the data transformation class, such as sometimes need to change the txtdataconvertor to Exceldataconvertor, at this time, you need to modify Customerdao source code, And in the introduction and use of the new Data transformation class also have to modify the source code of the Customerdao, the system is poor scalability, violation of the open and close principle, now need to reconstruct the scheme. |
In this example, because Customerdao is programmed for specific data conversion classes, you have to modify the source code of Customerdao when you add a new Data transformation class or replace a data transformation class. We can solve this problem by introducing abstract Data transformation classes, after introducing the abstract Data Transformation class Dataconvertor, Customerdao for the abstract class Dataconvertor programming, and the specific data transformation class name stored in the configuration file, in line with the dependency reversal principle. According to the principle of the substitution of the Richter scale, when the program runs, the specific data conversion class object will replace the Dataconvertor type object, and the program will not have any problems. Change the specific data conversion class without modifying the source code, only need to modify the configuration file, if you need to add a new specific data transformation class, as long as the addition of data transformation class as a subclass of Dataconvertor and modify the configuration file, the original code does not need to make any changes to meet the open and closed principle. The reconstructed structure is shown in 2:
Fig. 2 Structure diagram after reconstruction
In the above reconstruction process, we used the open and close principle, the Richter substitution principle and the dependence reversal principle, in most cases, these three design principles will appear at the same time, the opening and closing principle is the goal, the Richter substitution principle is the foundation, relies on the reversal principle is the means , they complement each other, complement each other, the goal is consistent, Only when analyzing the problem, the angle is different.
Five. Interface Isolation principle
Original link: http://blog.csdn.net/lovelion/article/details/7562842
The interface isolation principle is defined as follows:
Interface Isolation principle (Interface segregation Principle, ISP): use multiple specialized interfaces instead of a single total interface, i.e. the client should not rely on interfaces that it does not need, interface-oriented programming is a science, do not write the interface too fat , now people like thin, slender;
Based on the interface isolation principle, when an interface is too large, we need to split it into smaller interfaces, and the client using that interface needs only to know the methods associated with it. Each interface should assume a relatively independent role, do not do the things that should not do, the work should be done. In fact, this is to increase the interoperability of the interface, where the "interface" often has two different meanings: one refers to a type of the method characteristics of the collection, is merely a logical abstraction, and the other refers to a language specific "interface" definition, there is a strict definition and structure, For example, interface in the Java language. For these two different meanings, the way the ISP is expressed and what it means is different:
(1) When the "interface" is understood as a set of all the method features provided by a type, this is a logical concept, the division of the interface will directly bring the division of the type. The interface can be understood as a role, an interface can only represent a role, each role has its own specific interface, this principle can be called " role Isolation Principle ."
(2) If the "interface" is understood as a narrow language-specific interface, then the ISP expression means that the interface only provides the behavior that the client needs, the client does not need to hide the behavior, should provide the client with the smallest possible separate interface, rather than provide a large total interface . In an object-oriented programming language, implementing an interface requires implementing all of the methods defined in the interface, so it is not always convenient to use a large total interface, in order to make the interface a single function, it is necessary to put the methods of the large interface in different small interfaces according to their responsibilities, in order to ensure that each interface is more convenient to use. And all assume a single role. The interface should be as thin as possible, and the methods in the interface should be as few as possible, each interface contains only one client (such as a submodule or business logic Class) required methods, this mechanism is also called " Custom Service ", that is, to provide different clients with different interfaces.
The following is a simple example that deepens the understanding of the principle of interface isolation:
The Sunny software developer designed 1 interfaces for the customer data display module of a CRM system, where the method Dataread () is used to read data from a file, and the method Transformtoxml () is used to convert the data to XML format. Method Createchart () is used to create a chart, Method Displaychart () is used to display a chart, method CreateReport () is used to create a text report, and Method Displayreport () is used to display a text report. Figure 1 Initial design scheme chart In the actual use of the interface is not flexible, for example, if a specific data display class without data conversion (the source file itself is XML format), but because of the implementation of the interface, will have to implement the Transformtoxml () method declared in it (at least to provide a null implementation) If you need to create and display a chart, you need to implement methods to create and display text reports in addition to the methods associated with the chart, or the program compiles with an error. is now refactored using the interface isolation principle. |
In Figure 1, because there are too many methods defined in the interface Customerdatadisplay, that is, the interface assumes too much responsibility, on the one hand, the implementation class of the interface is very large, in different implementation classes have to implement all the methods defined in the interface, the flexibility is poor, If a large number of empty methods, will result in a large number of useless code in the system, affecting the quality of code, on the other hand, because the client program for the large interface, will be on a certain program to break the package of the program, the client sees the method should not be seen, no custom interface for the client . Therefore, the interface needs to be reconstructed according to the principle of interface isolation and the principle of single responsibility, and some of these methods are encapsulated in different small interfaces, ensuring that each interface is convenient to use and assumes a single role, each of which contains only one client (such as a module or class) that is required for the method.
By using the interface isolation principle, the refactoring of this example is shown in structure 2:
Fig. 2 Structure diagram after reconstruction
in the use of interface isolation principle, we need to pay attention to the granularity of the control interface, the interface can not be too small, if too small will lead to the system interface flooding, not conducive to maintenance, the interface can not be too large, too large interface will violate the principle of interface isolation, flexibility is poor, use is very inconvenient. in general, interfaces only contain methods that are customized for a particular class of users and should not force customers to rely on methods that they do not use.
Six. Dimitri Law
Original link: http://blog.csdn.net/lovelion/article/details/7563445
The Dimitri Law came from a research project called "Demeter" at Northeastern University in 1987 (Northeastern University). The Dimitri rule is also known as the least-knowledge principle (Leastknowledge Principle, LKP), which is defined as follows:
Dimitri (Law of Demeter, LoD): A software entity should interact with other entities as little as possible. |
If a system conforms to the Dimitri Law, then when one of the modules changes, it will minimize the impact of the other modules, the extension is relatively easy, this is the limit of communication between software entities, the Dimitri law requires limiting the width and depth of communication between software entities. The Dimitri law can reduce the coupling degree of the system, and keep the coupling between classes and classes loosely.
There are several defining forms of the Dimitri Law, including : don't talk to strangers , just communicate with your direct friends , in the Dimitri rule, for an object, its friends include the following categories:
(1) The current object itself (this);
(2) An object that is passed into the current object method in the form of a parameter;
(3) The member object of the current object;
(4) If the member object of the current object is a collection, then the elements in the collection are also friends;
(5) The object created by the current object.
Any object, if one of the above conditions is met, is the "friend" of the current object, or "stranger". When applying the Dimitri rule, an object can only interact with a direct friend and not interact directly with strangers, which reduces the coupling of the system, and changes in one object do not affect too many other objects.
The Dimitri law requires us to minimize interaction between objects when designing systems, and if two objects do not have to communicate directly with each other, then the two objects should not have any direct interaction, if one of the objects needs to invoke a method of another object, This call can be forwarded through a third party. In short, it is to reduce the coupling between existing objects by introducing a reasonable third party.
When applying the Dimitri rule to system design, pay attention to the following points : in the division of classes, we should try to create loosely coupled classes, the lower the coupling between classes, the more conducive to reuse, a loose coupling in the class once modified, will not cause too much impact on the associated class ; In the structure design of the class, each class should minimize the access rights of its member variables and member functions ; in the design of a class, a type should be designed as an immutable class whenever possible ; on references to other classes, one object's references to other objects should be minimized .
The following is a simple example to deepen the understanding of the Dimitri rule:
The CRM system developed by Sunny Software includes many business operations windows in which there is a complex interaction between some interface controls, and triggering of one control event causes multiple other interface controls to respond, for example, when a button is clicked, the corresponding list box ), combo Box (ComboBox), text Box (textbox), text label (label), and so on, will change, and in the initial design, the interaction between the interface controls can be simplified to the structure shown in 1: Figure 1 Schematic diagram of the initial design scheme In Figure 1, because of the complexity of the interaction between interface controls, the source code of the other controls that interact with it needs to be modified when new interface controls are added to the window, and the system is less extensible and does not make it easy to add and remove new controls. It is now refactored using Dimitri. |
In this example, you can reduce the coupling between interface controls by introducing an intermediate class (mediator) that is designed to control the interaction of interface controls. After the intermediate class is introduced, the direct reference is no longer occurring between the interface controls, but instead the request is forwarded to the Intermediate class and the intermediate class completes the call to the other control. When you need to add or remove new controls, you can simply modify the intermediate class, without modifying the source code of the new or existing control, as shown in structure 2:
Fig. 2 Structure diagram after reconstruction
A popular understanding of Java design Patterns