In our daily development, we often have to follow some principles and patterns. These are actually summarized by predecessors in development. No matter what software development we do, it will be beneficial and harmless to us, and we have mastered it. These principles and techniques will only help you improve your efficiency. This article summarizes these principles and explains their meaning, giving you reference value. I hope this article can inspire you and help you learn Java knowledge better. . apache php mysql
begin!
The basic principles (solid) of object-oriented are five, but in addition to these are often mentioned In addition to the five, there are Demeter's Law and the Principle of Synthesis and Reuse, etc., so in common articles, there are six or seven principles; in addition, I will also give some other related books and information on the Internet. The emerging principle;
Single-Responsibility Principle, a class, it is best to do only one thing, only one cause it to change. The single responsibility principle can be seen as an extension of the object-oriented principle of low coupling and high cohesion. Responsibility is defined as the cause of change to improve cohesion and reduce the cause of change.
Definition
An object should only contain a single responsibility, and the responsibility should be completely encapsulated in a class. (Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.), that is, it is also defined that there is one and only one reason for the class to change. Click here to view detailed explanations of 9 solutions for high-availability architecture design.
Principle Analysis
The more responsibilities a class (or as large as a module or as small as a method) bears, the less likely it is to be reused, and if If a class assumes too many responsibilities, it is equivalent to coupling these responsibilities together. When one of the responsibilities changes, it may affect the operation of other responsibilities.
The responsibilities of a class mainly include two aspects: data responsibilities and behavioral responsibilities. Data responsibilities are reflected through its attributes, while behavioral responsibilities are reflected through its methods.
The single responsibility principle is a guideline for achieving high cohesion and low coupling. It can be found in many code refactoring techniques. It is the simplest but most difficult to apply. The principle requires designers to discover the different responsibilities of a class and separate them, and discovering multiple responsibilities of a class requires designers to have strong analysis and design capabilities and relevant refactoring experience.
Advantages
Reduce the complexity of the class, and the responsibilities of the class are clear and clear. For example, data responsibilities and behavioral responsibilities are clear and clear.
Improve the readability and maintainability of the class,
Reduce the risk caused by changes, changes are essential, if the interface If single responsibility is done well, an interface modification will only affect the corresponding class and will have no impact on other interfaces. This will be of great help to the scalability and maintainability of the system.
Note: The single responsibility principle proposes a standard for writing programs, using "responsibility" or "reason for change" to measure whether the interface or class design is reasonable, but "responsibility" " and "reason for change" have no specific standards. What responsibilities should a class be responsible for? How are these responsibilities detailed? Will there be an interface or class after refinement? These need to be considered based on the actual situation. Varies from project to project and environment to environment.
Example
Separation of Entity, DAO, Service, Controller, Util, etc. in SpringMVC.
Open - ClosedPrinciple,OCP, open for extension, closed for modification (core principle of design pattern)
Definition
A software entity (such as a class, module, and function) should be open for extension and closed for modification. This means that a system or module is open to extensions and closed to modifications. A good system can expand your functions without modifying the source code. The key to realizing the opening and closing principle is abstraction.
Principle Analysis
When software entities change due to needs, try to extend existing software entities to provide new behaviors to meet the needs of the software meet new requirements instead of modifying existing code, so that the changing software has a certain degree of adaptability and flexibility. Existing software modules, especially the most important abstraction layer modules, cannot be modified, which gives the changing software system a certain degree of stability and continuity.
The key to realizing the open-closed principle is abstraction: in the "open-closed" principle, abstract classes or interfaces are not allowed to be modified, and concrete implementation classes are allowed to be extended. ,Abstract classes and interfaces play an extremely important role in the "open-closed" principle. That is to predict possible changing requirements and to foresee all possible known extensions..So "abstraction" is the key here!
The closed principle of variability: Find the variable factors of the system and encapsulate them. This is the best implementation of the "open-closed" principle. Don't put your variable factors in Multiple classes, or scattered in every corner of the program. You should encapsulate the variable factors... and be sure not to encapsulate the variable factors you use together. The best solution is to enclose your variable factors in blocks. Variable factors! Avoid the appearance of super large classes, super long classes, and super long methods!! Add an artistic flavor to your program, and making the program artistic is our goal!
Example
The template method pattern and the observer pattern in the design pattern are both excellent embodiments of the opening and closing principle. Click here to view detailed explanations of 9 solutions for high-availability architecture design.
Liskov Substitution Principle, LSP: Anywhere a base class can appear, a subclass can also appear; this idea It is expressed as a constraint specification on the inheritance mechanism. Only when a subclass can replace its base class can the system be guaranteed to recognize the subclass during runtime. This is the basis for ensuring inheritance reuse.
Definition
The first definition method is relatively strict: if for every object o1 of type S, there is an object o2 of type T, so that all objects defined with T When all objects o1 of program P are replaced with o2, the behavior of program P does not change, then type S is a subtype of type T.
The second, easier-to-understand definition: all places that reference the base class (parent class) must be able to transparently use objects of its subclasses. That is, the subclass must be able to replace the base class from where it appears. Subclasses can also add new behaviors based on the base class.
(The Liskov substitution principle was proposed in 1994 by Barbara Liskov, the 2008 Turing Award winner, the first female doctor of computer science in the United States, professor at MIT, and Professor Jeannette Wing at Carnegie Mellon University. .The original text is as follows: Let q(x) be a property provableabout objects x of type T. Then q(y) should be true for objects y of type Swhere S is a subtype of T. )
Principle Analysis
is about the relationship between base classes and subclasses. Only when this relationship exists, the Liskov substitution principle exists. A square is a rectangle is a classic example of understanding the Liskov substitution principle.
The Liskov substitution principle can be expressed in a popular way: if you can use base class objects in software, then you must be able to use its subclass objects. If the base class is replaced with its subclasses, the program will not generate any errors or exceptions. The reverse is not true. If a software entity uses a subclass, it may not be able to use the base class.
The Liskov substitution principle is one of the important ways to implement the opening and closing principle. Since subclass objects can be used wherever base class objects are used, base classes should be used as much as possible in the program. Type to define the object, and then determine its subclass type at runtime, and replace the parent class object with the subclass object.
(Interface Segregation Principle, ISL): The client should not rely on interfaces that it does not need . (This law is consistent with Demeter's law)
Definition
The client should not rely on interfaces that it does not need.
Another definition method: Once an interface is too large, it needs to be divided into smaller interfaces. The client using the interface only needs to know the methods related to it.
Note that the interface in this definition refers to the defined method. For example, calling a public method of a class from outside. This method is an interface to the outside world.
Principle Analysis
1) The principle of interface isolation refers to using multiple specialized interfaces instead of using a single total interface. Each interface should assume a relatively independent role, no more and no less. It should not do things that it should not do, but should do everything that should be done.
An interface only represents one role, and each role has its own specific interface. This principle can be called the "role isolation principle".
The interface only provides the behaviors that the client needs, that is, the required methods. The behaviors that the client does not need are hidden. The client should be provided with a separate interface as small as possible. Rather than providing a large total interface.
2) When using the interface isolation principle to split an interface, you must first satisfy the single responsibility principle, define a set of related operations in an interface, and meet the premise of high cohesion. The fewer methods in the interface, the better.
3) You can use customized services when designing the system, that is, providing interfaces with different widths for different clients, only providing the behaviors that users need, and hiding behaviors that users do not need.
Dependency-Inversion Principle should rely on abstraction rather than specific implementation. Specifically, high-level modules do not depend on Low-level modules, both of which depend on abstractions. Abstraction does not depend on concrete, concrete depends on abstraction.
Definition
High-level modules should not depend on low-level modules, they should all depend on abstractions. Abstractions should not depend on details, details should depend on abstractions. Simply put, the dependency inversion principle requires clients to rely on abstract couplings. Principle expression:
1) Abstraction should not depend on details; details should depend on abstraction;
2) Programming should be for interfaces, not for implementation.
Principle Analysis
1) If the opening and closing principle is the goal of object-oriented design, the dependency inversion principle is the means to achieve the "opening and closing" principle of object-oriented design. If you want to achieve the best "opening and closing" principle, you must abide by the dependency inversion principle as much as possible. It can be said that the dependency inversion principle is the best specification for "abstraction"! I personally feel that the dependence inversion principle is also a complement to the Richter substitution principle. Once you understand the Liskov substitution principle, it should be easy to understand the dependency inversion principle.
2) One of the common ways to implement the dependency inversion principle is to use abstract classes in the code and place concrete classes in the configuration file.
3) Coupling between classes: zero coupling relationship, concrete coupling relationship, abstract coupling relationship. The Dependency Inversion Principle requires clients to rely on abstract coupling. Coupling in an abstract manner is the key to the Dependency Inversion Principle.
Example
To understand this dependency inversion, first we need to understand the concept of dependency in object-oriented design:
Dependency (Dependency): It is a usage relationship, specific things Changes may affect other things that use that thing. Use dependency relationships when you need to indicate that one thing uses another thing. (Assuming that changes in class A cause changes in class B, then class B is said to depend on class A.) In most cases, the dependency relationship is reflected in the method of a certain class using an object of another class as a parameter. In UML, dependency relationships are represented by dashed lines with arrows, pointing from the dependent party to the dependent party.
Example: A certain system provides a data conversion module that can convert data from different data sources into multiple formats, such as data from a database (DatabaseSource) or data from a text file ( TextSource), the converted format can be an XML file (XMLTransformer), an XLS file (XLSTransformer), etc.
Due to changes in requirements, the system may need to add new data sources or new file formats. Each time a new type of data source or new type of file is added, format, the source code of the client class MainClass needs to be modified in order to use the new class, but it violates the opening and closing principle. It is now refactored using the dependency inversion principle. Click here to view detailed explanations of 9 solutions for high-availability architecture design.
Of course, depending on the specific situation, AbstractSource can also be injected into AbstractStransformer. There are three dependency injection methods:
<ol class="hljs-ln list-paddingleft-2"><li><p class="hljs-ln-line"><span class="hljs-comment"><span class="hljs-comment">/** </span></span></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * 依赖注入是依赖AbstractSource抽象注入的,而不是具体 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">* DatabaseSource </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">* </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">abstract</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-class" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractStransformer</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{ </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">private</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> AbstractSource source; </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/** </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * 构造注入(Constructor Injection):通过构造函数注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AbstractStransformer</span><span class="hljs-params">(AbstractSource source)</span></span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{ </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">this</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">.source = source; </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> } </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/** </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * 设值注入(Setter Injection):通过Setter方法注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * </span><span class="hljs-doctag" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">@param</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> source : the sourceto set </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSource</span><span class="hljs-params">(AbstractSource source)</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{ </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">this</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">.source = source; </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> } </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/** </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * 接口注入(Interface Injection):通过接口方法注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * </span><span class="hljs-doctag" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">@param</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> source </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transform</span><span class="hljs-params">(AbstractSource source )</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{ </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> source.getSource(); </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> System.out.println(</span><span class="hljs-string" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">“Stransforming …”</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">); </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> } </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">}</span></p></li></ol>
##(Composite/Aggregate ReusePrinciple, CARP): Use object combination as much as possible, and It is not the inheritance relationship that achieves the purpose of software reuseDefinitionIt is often called the Composite Reuse Principle or CRP. Try to use object combination instead of inheritance to achieve reuse purpose. It is to use some existing objects in a new object to make them part of the new object; the new object achieves the purpose of reusing existing functions by delegating to these objects. In short, try to use composition/aggregation and try not to use inheritance. Principle Analysis1) In object-oriented design, existing designs and implementations can be reused in different environments through two basic methods, namely through combination/aggregation relationships or through inherit. Inheritance and reuse: simple to implement and easy to extend. Destroys the encapsulation of the system; the implementation inherited from the base class is static, cannot be changed at runtime, and does not have enough flexibility; it can only be used in limited environments. ("White box" reuse) Combination/aggregation reuse: The degree of coupling is relatively low, and the operations of member objects are selectively called; it can be done dynamically at runtime. ("Black box" reuse) 2) Combination/aggregation can make the system more flexible, reduce the coupling between classes, and changes in one class will have relatively little impact on other classes, so generally The first choice is to use combination/aggregation to achieve reuse; secondly consider inheritance. When using inheritance, you need to strictly follow the Liskov substitution principle. Effective use of inheritance will help understand the problem and reduce complexity, while abuse of inheritance will lead to It increases the difficulty of system construction and maintenance and the complexity of the system, so inheritance reuse needs to be used with caution. 3) This principle and the Liskov substitution principle are complementary to each other. Both are specifications for the concrete realization of the "open-close" principle. Violating this principle, the "open-closed" principle cannot be realized. First, we must understand the concepts of synthesis and aggregation:
Note: What is the difference between aggregation and combination?Synthesis (combination): Indicates the relationship between a whole and a part, and refers to a relationship that exists based on the whole (the whole and the parts cannot be separated); for example, the eyes and mouth are a combination relationship for the head. Without the head, there would be no Eyes and mouth, they are inseparable. In UML, composition relationships are represented by straight lines with solid diamonds.
Aggregation: Aggregation is a stronger dependency relationship than composition, and also represents the relationship between the whole and the part (the whole and the part can be separated); such as the relationship between screws and car toys , the toy can still be used on other devices after the screws are detached. In UML, aggregation relationships are represented by straight lines with hollow diamonds.
Law of Demeter
(Law of Demeter, LoD: Classes in the system, try not to interact with other classes, reduce classes The degree of coupling between
Definition
is also called the Least Knowledge Principle (or abbreviated as LKP) and is defined in several forms:
Don't talk to "strangers". The English definition is: Don't talk to strangers.
Only communicate with your immediate friends. The English definition is: Talk only to your immediate friends.
Each software unit has minimal knowledge of other units, and is limited to those software units closely related to its own unit.
Simply put, that is, an object should know as little as possible about other objects. A class should know the least about the class that it needs to couple or call. The internals of you (the coupled or called class) are No matter how complicated it is, it doesn't matter to me. That's your business. I only know the public methods you provide. I only call so many and don't care about anything else.
Law Analysis
Friend Category:
In Demeter's Law, for an object, its friends include the following categories: (1) The current object itself (this); (2) The object passed into the method of the current object as a parameter; (3) The member object of the current object; (4) If the member object of the current object is a set, then the elements in the set are also friends; (5) The current object The created object.
Any object, if it meets one of the above conditions, is a "friend" of the current object, otherwise it is a "stranger".
Narrow and broad laws:
In the narrow sense of Demeter's law, if two classes do not need to communicate directly with each other, then the two classes should not directly communicate with each other. Function, if one of the classes needs to call a certain method of another class, the call can be forwarded through a third party.
Narrow sense of Dimit's law: It can reduce the coupling between classes, but it will Adding a large number of small methods to the system and scattering them in every corner of the system can simplify the local design of a system, because each part will not be directly related to distant objects, but it will also make the system different. The communication efficiency between modules is reduced, making it difficult to coordinate between different modules of the system. Click here to view detailed explanations of 9 solutions for high-availability architecture design.
Generalized Demeter's Law: refers to the relationship between objects The control of information flow, flow direction and impact of information is mainly the control of information hiding. Information hiding can decouple various subsystems, allowing them to be developed, optimized, used and modified independently, and can also promote software Reuse, because each module does not depend on other modules, so each module can be used independently in other places. The larger a system is, the more important it is to hide information, and the more obvious the importance of information hiding becomes.
The main purpose of Dimit's Law is to control the overload of information.
In terms of class division, we should try to create loosely coupled classes. The lower the degree of coupling between classes, the more conducive to reuse. A loosely coupled class Once a class in is modified, it will not have much impact on the associated classes;
In terms of class structure design, each class should minimize its member variables and member functions Access permissions;
In class design, whenever possible, a type should be designed as an immutable class;
In terms of access to other Regarding class references, the references of one object to other objects should be minimized.
Example
Appearance mode Facade (structural)
Dimiter's Law and Design Pattern Facade mode, Mediator mode
Classes in the system should try not to interact with other classes to reduce the coupling between classes, because in your system, when expanding, you may need to modify these classes, and classes are different from each other. The relationship between them determines the complexity of modification. The more interactions there are, the greater the difficulty of modification. On the contrary, if the interactions are smaller, the difficulty of modification will be smaller. For example, class A depends on class B, and class B depends on class C. When you modify class A, you have to consider whether class B will be affected, and whether the impact of class B will affect class C. If class C depends on class D at this time, haha, I think such modifications will be bearable.
Other principles of object-oriented design
Encapsulation of changes
Use less inheritance Multi-purpose composition
Aimed at interface programming and not implementation programming
Strive for loose coupling design between interactive objects
Classes should be closed to extension development and modification (open and closed OCP Principle)
Rely on abstraction, do not rely on concrete classes (Dependency Inversion DIP Principle)
Close Friend Principle: Only talk to friends (Least Knowledge Principle, Demeter's Law)
Description: An object should know as little as possible about other objects, keep method calls within bounds, and only call methods that belong to the following scope: The object itself (local method) The components of the object are passed in as method parameters Object Any object created or instantiated by this method
Don’t come to me (call me) I will come to you (call you) (Hollywood principle)
A class has only one reason for its change (Single Responsibility SRP Principle)
Can you explain the Liskov Substitution Principle?
Strict definition: If for every object o1 of type S, there is Object o2 of type T makes the behavior of all programs P defined with T unchanged when all objects are replaced with o2 by o1, then type S is a subtype of type T.
Popular statement: All places that reference a base class (parent class) must be able to transparently use objects of its subclasses. That is to say, a subclass can extend the functions of the parent class, but it cannot change the original functions of the parent class. It contains the following 4 levels of meaning:
Subclasses can implement abstract methods of the parent class, but cannot override non-abstract methods of the parent class.
You can add your own unique methods to subclasses.
When a method of a subclass overrides a method of a parent class, the preconditions of the method (that is, the formal parameters of the method) are looser than the input parameters of the parent class method.
When a method of a subclass implements an abstract method of a parent class, the postconditions of the method (that is, the return value of the method) are more stringent than those of the parent class.
Under what circumstances will Dimit's Law be violated? Why is this a problem?
Demeter's Law recommends "only talk to friends, not strangers" to reduce coupling between classes.
Give me an example of a design pattern that conforms to the open-close principle?
The open-closed principle requires that your code be open to extensions and closed to modifications. This means that if you want to add a new feature, you can easily add new code without changing the already tested code. There are several design patterns based on the open-close principle, such as the strategy pattern. If you need a new strategy, you only need to implement the interface and add configuration, without changing the core logic. A working example is the Collections.sort() method. This is based on the strategy pattern and follows the open-closed principle. You do not need to modify the sort() method for new objects. All you need to do is implement your own Comparator interface. .
When to use flyweight mode (fly weight mode)?
Flyweight mode avoids creating too many objects by sharing objects. In order to use the flyweight pattern, you need to ensure that your objects are immutable so that you can share them safely. The String pool, Integer pool and Long pool in the JDK are all good examples of using the Flyweight pattern.
end:
If you have any questions, you can ask them and let’s discuss them together.
Related articles:
Basic knowledge you must know about JavaScript
24 Design Patterns and 7 Principles in Java
Related videos:
JavaScript Advanced Framework Design Video Tutorial
The above is the detailed content of Do all Java architects know these 6 design principles? Must master. For more information, please follow other related articles on the PHP Chinese website!