Statement: This series of blog reference "Big Talk design mode", author Geoscience.
It is generally considered that code that complies with the following six principles is easily extensible and reusable:
The six principles of any object-oriented language should be adhered to, in order to make your code easy to expand high-dose to meet the six principles, not necessarily strictly according to a design pattern, but if your code conforms to these six principles, then your code is good code, good code is not necessarily strictly in accordance with the design pattern written code.
1. Single Responsibility
Definition: Do not have more than one cause for class changes. In layman's terms, a class is responsible for only one responsibility.
Scenario: 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 the function that is normally functioning P2 to fail with the relationship such as:
Modify: Follow the principle of single responsibility. Set up two classes T1, T2 respectively, so that T1 complete the functions 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, it does not cause the responsibility to P1 the risk of failure, structure such as:
Advantages:
1), can reduce the complexity of the class, a class is only responsible for a responsibility, logic simple;
2), improve the readability of the class, improve the maintainability of the system;
3), the risk of change caused by the reduction, change is inevitable.
2. The principle of substitution on the Richter scale
Definition: All references to the base class must be able to use the object of its subclass transparently, that is, the subclass can extend the functionality of the parent class, but not the original function of the parent class
Scenario: 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, such as:
The Countpricebyjkl class inherits from the Countprice class, and COUNTPRICEBYJKL overrides the Count () method, which may affect the functionality of the original Count method.
Modify: Follow the Richter substitution principle when using inheritance. When Class B inherits from 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.
3. Dependency 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.
This is the most difficult to understand, usually in the framework of the project to use, for example, the business logic layer is a high-level module relative to the data layer, because the business logic layer needs to call the data layer to connect to the database, but to achieve scalable high-reuse, try not to let the business logic layer depends on the data layer, An interface can be abstracted from the data layer, allowing the business logic layer to rely on this abstract interface.
Scenario: Class A (High-level module) directly depends on class B (Low-layer module), if you want to change class A to rely on Class C (lower module), you must modify the code of Class A to achieve. 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.
The Autosystem class is directly dependent on the Hondacar and Fordcar two classes, resulting in a high coupling, autosystem classes want to manipulate Hondacar or fordcar must create the corresponding object directly.
Modify: 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, such as:
After this modification, Honda and Ford implemented the ICAR interface, providing the run, stop, and turn function methods, Autosystem dependent icar interface, forcing Autosystem to rely on the abstract interface, This allows the Autosystem class to cope with more demand changes.
Advantages:
1), low-level modules as far as possible to have an abstract class or interface, or both.
2), the declaration type of the variable as far as possible is abstract class or interface.
3), the use of inheritance to follow the Richter replacement principle.
4. Interface Isolation 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.
Scenario: 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, such as:
Modify: 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.
Attention:
1), the interface as small as possible, but there must be a limit. 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.
2), to customize the service for the interface-dependent class, exposes only to the calling class the method it requires, and the method it does not need is hidden. A minimal dependency can be established only by focusing on providing a customized service for a module.
3), improve cohesion, reduce external interaction. Enable the interface to do the most things with the least amount of method.
5. Dimitri rule (least known principle)
Definition: An object should have minimal knowledge of other objects.
Scenario: The closer the relationship between classes and classes, the greater the coupling, and the greater the impact on another class when one class changes.
The simple understanding is that cohesion, a class of methods and properties can be privatized as far as possible with private.
Attention:
1), only communicate with the direct friends, do not talk with strangers.
2), excessive use of the principle, will lead to 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.
6. Opening and closing principle
Definition: A software entity such as classes, modules, and functions should be open to extensions and closed for modification.
Scenario: During the software lifecycle, because changes, upgrades, and maintenance are required to modify 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.
Recommendation: When software requirements change, try to implement changes by extending the behavior of the software entities, rather than by modifying existing code.