Design pattern
reference resources:
[1]: http://c.biancheng.net/view/1322.html "" C language Chinese network ""
[2]: https://www.bilibili.com/video/BV1Np4y1z7BU
Design principles
Opening and closing principle
Open for extension and close for modification. The code can be extended and cannot be modified
Interfaces and abstract classes are required.
When the program needs to be extended, there is no need to modify the source code, just add a new implementation class
When setting a new skin for SougouInput, we don't need to modify the specific code. We just need to write skin3 and implement AbstractSkin() and setSkin() (setSkin is called by the outside world).
Richter substitution principle
Wherever a parent class can appear, a child class must appear. That is, subclasses can extend the functions of the parent class, but cannot modify the functions of the parent class. Subclasses should not override the methods of the parent class as much as possible. Overriding the parent method by a subclass will reduce the reusability of the code. If a subclass must override the parent method, it should not affect the meaning of the parent method
When the program violates the Richter substitution principle, that is, when the subclass appears in the position of the parent class, the program will make an error. At this time, the correct modification method is to cancel the inheritance relationship between them and redesign the relationship between them.
Classic examples: "a square is not a rectangle" and "a kiwi bird is not a bird".
package principle; public class LSPtest { public static void main(String[] args) { Bird bird1 = new Swallow(); Bird bird2 = new BrownKiwi(); bird1.setSpeed(120); bird2.setSpeed(120); System.out.println("If flying 300 km:"); try { System.out.println("The swallow will fly" + bird1.getFlyTime(300) + "hour."); System.out.println("Kiwi will fly" + bird2.getFlyTime(300) + "Hours."); } catch (Exception err) { System.out.println("An error has occurred!"); } } } //birds class Bird { double flySpeed; public void setSpeed(double speed) { flySpeed = speed; } public double getFlyTime(double distance) { return (distance / flySpeed); } } //Swallows class Swallow extends Bird { } //Kiwi birds class BrownKiwi extends Bird { public void setSpeed(double speed) { flySpeed = 0; } }
If flying 300 km: The swallow will fly 2.5 hour. Kiwi will fly Infinity Hours.
The reason is that although kiwi is also a bird, under the current situation, kiwi is not a bird (kiwi can't fly). At this time, if we inherit Kiwi from birds, it will violate the principle of Richter substitution
The following are improvements
Dependency Inversion Principle
High level modules should not rely on low-level modules, but both should rely on abstraction; Abstraction should not depend on details, details should depend on abstraction. That is, it requires us to face Abstract Programming. Similar to the specific embodiment of the opening and closing principle.
The purpose of dependency inversion principle is to reduce the coupling between classes through interface oriented programming, so we can meet this rule in the project as long as we follow the following four points in actual programming.
- Each class should provide interfaces or abstract classes, or both.
- The declaration type of variables should be interfaces or abstract classes.
- No class should derive from a concrete class.
- Try to follow the Richter substitution principle when using inheritance.
Interface isolation principle
The functions contained in the interface should be small and fine, not large and complete.
When applying the interface isolation principle, it should be measured according to the following rules.
1. The interface should be as small as possible, but limited. An interface serves only one sub module or business logic. 2. Customize services for classes that depend on interfaces. Only the methods required by the caller are provided, and the methods not required are shielded. 3. Understand the environment and refuse to follow blindly. Each project or product has selected environmental factors. Different environments lead to different standards for interface splitting, and in-depth understanding of business logic. 4. Improve cohesion and reduce external interaction. Make the interface do the most with the least methods.
Single responsibility principle
Each class should focus on doing one thing or one kind of thing
For example, if a class has only one manager, the monitor needs to manage learning, discipline and hygiene. At this time, the monitor has multiple responsibilities, many and miscellaneous tasks, and it is very easy to make mistakes.
At this time, we can set up the study committee to undertake the responsibility of the monitor's management and learning, the discipline committee to undertake the responsibility of the monitor's management and discipline, and the health committee to undertake the responsibility of the monitor's management of health. The monitor only needs to be responsible for managing all the members. At this time, each person has a single responsibility
The principle of interface isolation is very similar to that of single responsibility. Both of them are to improve the cohesion of classes and reduce the coupling between them, reflecting the idea of encapsulation, but they are different:
-
The single responsibility principle focuses on responsibilities, while the interface isolation principle focuses on the isolation of interface dependencies.
-
The single responsibility principle is mainly a constraint class, which aims at the implementation and details of the program; The principle of interface isolation mainly restricts the interface, and mainly aims at the construction of abstraction and the overall framework of the program.
Dimitri principle
Also known as the principle of least knowledge. If two software entities do not need to communicate directly, there should be no direct mutual call, and the call can be forwarded through a third party. Its purpose is to reduce the coupling between classes and improve the relative independence of modules.
Example 1] examples of the relationship between stars and brokers.
Analysis: because stars devote themselves to art, many daily affairs are handled by brokers, such as meeting with fans, business negotiation with media companies, etc. The brokers here are friends of stars, while fans and media companies are strangers, so it is suitable to use Dimitri's law. Its class diagram is shown in Figure 1.
package principle; public class LoDtest { public static void main(String[] args) { Agent agent = new Agent(); agent.setStar(new Star("Lin Xinru")); agent.setFans(new Fans("Fan Han Cheng")); agent.setCompany(new Company("China Media Co., Ltd")); agent.meeting(); agent.business(); } } //agent class Agent { private Star myStar; private Fans myFans; private Company myCompany; public void setStar(Star myStar) { this.myStar = myStar; } public void setFans(Fans myFans) { this.myFans = myFans; } public void setCompany(Company myCompany) { this.myCompany = myCompany; } public void meeting() { System.out.println(myFans.getName() + "With stars" + myStar.getName() + "We met."); } public void business() { System.out.println(myCompany.getName() + "With stars" + myStar.getName() + "Negotiate business."); } } //Star class Star { private String name; Star(String name) { this.name = name; } public String getName() { return name; } } //fans class Fans { private String name; Fans(String name) { this.name = name; } public String getName() { return name; } } //Media company class Company { private String name; Company(String name) { this.name = name; } public String getName() { return name; } }
Fan Han Cheng met with star Lin Xinru. China Media Co., Ltd. negotiated business with star Lin Xinru.
Composite principle
Composite Reuse Principle is also called combination / aggregation Reuse Principle. It requires that when reusing software, we should first use association relations such as composition or aggregation, and then consider using inheritance relations.
Coupling can be reduced