1. Opening and closing principle (open-closed Principle, OCP)
definition: software entities should be open to extensions and closed for modifications. This is a bit more professional, more popular, that is: The software system contains a variety of components, such as modules (Modules), classes (Classes) and Functions (Functions), and so on, should not modify the existing code on the basis of the expansion of new features. The original "open" in the principle of opening and shutting, refers to the expansion of the function of the component is open, is allowed to expand the function of it; "Closed" in the opening and closing principle refers to the modification of the code is closed, that is, the original code should not be modified.
The origin of the problem: There is a cause for everything. Let's take a look at the reason why the opening and closing principle. During the software life cycle, because of changes, upgrades, and maintenance that require modifications to the software's original code, errors may be introduced into the old code, or we will have to refactor the entire functionality and require the original code to be re-tested. This has a particularly large impact on our entire system, which also fully demonstrates the coupling of the system if too high, will greatly increase the later expansion, maintenance. In order to solve this problem, people have summed up the principle of opening and closing. The solution to the opening and closing principle is still decoupled. So, our most fundamental task in object-oriented development is decoupling.
Workaround: When the software needs to change, try to make changes by extending the behavior of the software entities, rather than modifying the existing code to achieve the change.
Summary: The open and close principle has the idealistic color, says is very abstract, it is the object-oriented design ultimate goal. Several other principles can be seen as the realization of the open and closed principle. We want to build the framework with abstractions and implement the extension details.
2. Single Duty principle (Responsibility Principle)
Definition: A class that has only one cause that causes it to change. That is, there should be only one duty.
Each responsibility is an axis of change, and if a class has more than one responsibility, these responsibilities are coupled together. This can lead to fragile designs. When a duty changes, other responsibilities may be affected. In addition, multiple responsibilities are coupled together, which can affect reusability. For example, to achieve separation of logic and interface. One point to note is that the single responsibility principle is not only specific to object-oriented programming, so long as it is modular programming, it is necessary to follow this important principle.
The origin of the problem: class T is responsible for two different duties: responsibility P1, Responsibility P2. When a class T needs to be modified due to a change in the duty P1 requirements, it is possible to cause a normal function to malfunction P2 functionality.
Solution: set up two classes T1, T2 respectively, so that T1 complete responsibility P1 function, T2 complete functions P2 function. In this way, when the class T1 is modified, the responsibility is not P2 the risk of failure, and similarly, when T2 is modified, the responsibility is not P1 the risk of failure.
3. Richter Replacement principle (Liskov Substitution Principle)
definition: subtypes must be able to replace their parent types. Note that here can be two words. Some people also joked that the son of a mouse could punch a hole.
problem Origin: There is a functional P1, which is done by Class A. Now need to extend the function P1, the function of the extension is P, where p is composed of the original function P1 and the new function P2. The new function p is done by subclass B of Class A, and sub-class B, while completing the new function P2, may cause the original function P1 to fail.
Workaround: When Class B inherits Class A, try not to rewrite the parent class A's method, but also try not to reload the parent Class A's method, except to add a new method to complete new functionality P2
Summary: all references to the parent class must be able to use the object of its subclass transparently. Subclasses can extend the functionality of the parent class, but not the original function of the parent class: Subclasses can implement the abstract methods of the parent class, and subclasses can also add their own unique methods, but not the non-abstract methods of the parent class. When a method of a subclass overloads a method of the parent class, the method's preconditions (that is, the parameter of the method) are more lenient than the input parameters of the parent class method. When a method of a subclass implements an abstract method of the parent class, the post condition of the method (that is, the return value of the method) is stricter than the parent class.
4. Dimitri (Law of Demeter)
definition: the Dimitri rule is also known as the least known principle, that is, an object should keep a minimum of knowledge of other objects. If two classes do not have to communicate directly with each other, then these two classes should not have a direct interaction. If one of the classes needs to invoke a method of another class, the call can be forwarded through a third party. Simply defined as communicating only with a direct friend. Let's start by explaining what a direct friend is: Each object has a coupling relationship with other objects, so long as there is a coupling between the two objects, we say that the two objects are friends. There are many ways of coupling, dependence, association, composition, aggregation and so on. In this case, we call the class in the member variable, method parameter, method return value as a direct friend, and the class appearing in the local variable is not a direct friend. In other words, unfamiliar classes are best not to appear inside the class as a local variable.
The problem is: The closer the relationship between classes and classes, the greater the coupling, and the greater the impact on another class when one class changes.
It was first proposed by Ian Holland of the American Northeastern University in 1987. In layman's terms, it is a class that knows as little as possible about the classes it relies on. That is to say, for a dependent class, no matter how complex the logic, as far as possible to encapsulate the logic inside the class, outside the public method provided, not to disclose any information. The Dimitri rule also has a simpler definition: communicate only with direct friends.
Workaround: Minimize the coupling between classes and classes. Since we began to touch programming, we have learned the general principles of software programming: low-coupling, high cohesion. Whether it is process-oriented programming or object-oriented programming, it is possible to increase the code reuse rate by minimizing the coupling between the modules.
The purpose of the Dimitri law is to reduce the coupling between classes, because each class reduces unnecessary dependencies, so it does reduce the coupling relationship. But everything has degrees, although can avoid and non-direct class communication, but to communicate, will inevitably through an "intermediary" to occur. Therefore, excessive use of the Dimitri principle, will produce a large number of such intermediaries and transfer classes, resulting in greater complexity of the system. Therefore, in the adoption of Dimitri Law, we should weigh repeatedly, not only to achieve a clear structure, but also high cohesion and low coupling.
5. Dependency inversion principle (dependence inversion Principle)
definition: high-level modules should not be dependent on the lower layers, both should rely on their abstraction; abstractions should not depend on detail; detail should be dependent on abstraction. The central idea is interface-oriented programming
The problem is that class A is directly dependent on class B, and if you want to change Class A to dependency Class C, you must modify the code of Class A to achieve it. In this scenario, Class A is typically a high-level module that is responsible for complex business logic, and Class B and Class C are low-layer modules that are responsible for basic atomic operations, and if Class A is modified, it poses unnecessary risks to the program.
Workaround: Modify Class A to dependent interface I, Class B and Class C each implement interface I, Class A through interface I indirectly with Class B or Class C, it will greatly reduce the chance to modify Class A.
In actual programming, we generally need to do the following 3 points:
1). Low-level modules try to have an abstract class or interface, or both.
2). The declaration type of a variable should be an abstract class or interface as much as possible.
3). Follow the Richter substitution principle when using inheritance.
The use of dependency inversion principle in particular for the cooperation of many people to bring great convenience, the more people involved in collaborative development, the larger the project, the use of reliance leads to the significance of the principle of the more important.
Summary: The dependency inversion principle is to interface programming, understand the interface-oriented programming, but also understand the dependency inversion.
6. Interface Isolation principle (Interface segregation Principle)
definition: The client should not rely on interfaces it does not need, and the dependency of one class on another should be based on the smallest interface.
The problem is that Class A relies on class B through interface I, Class C through interface I relies on Class D, and if interface I is not the smallest interface for Class A and Class B, then Class B and Class D must implement methods that they do not need
Workaround:1, use the delegate to separate the interface. 2, using multiple inheritance to separate the interface. 3. Split the bloated interface I into separate interfaces, and Class A and Class C are dependent on the interfaces they need. That is, the principle of interface isolation.
Summary: We in the code writing process, the use of interface isolation principle, must be moderate, the interface design is too large or too small is not good. The refinement of the interface can improve the design flexibility is not a fact, but if too small, it will result in an excessive number of interfaces, resulting in complex designs. So be sure to be modest. When designing an interface, it is possible to practice this principle accurately by taking more time to think and plan.
7. Synthesis/Aggregation principles (Composite/aggregate reuse Principle,carp)
definition: Others are called synthetic multiplexing principles, and use compositing/aggregation as much as possible, rather than using class inheritance. In other words, it is the place where you can use synthesis/aggregation, never inherit.
Why use composition/aggregation as much as possible instead of class inheritance?
1. The inheritance of an object is defined at compile time, so it is not possible to change the implementation of subclasses inherited from the parent class at run time
2. The implementation of the subclass has a very close dependency on its parent class, so that any changes in the parent implementation will inevitably cause the subclass to change
3. When you reuse a subclass, if the inherited implementation is not suitable for solving the new problem, the parent must override or be replaced by a more appropriate class, which limits flexibility and ultimately limits reusability.
Summary: these principles in the design pattern embodied in the dripping, design pattern is to achieve these principles, so as to achieve code reuse, enhance the scalability of the system. So the design pattern is regarded by many people as the classics. We can understand these design principles slowly through a good research design pattern.
The seven design principles of C # facing objects