Design Patterns
Decorator Design pattern
Decorator patterns for extending system functionality.
For example, if we have a duck class, we can call its duck calling method. We have initialized a duck object, how to count how many times this object has called, that is, how many times its duck calling method has been called? Remember that OCP principles don't allow us to modify duck classes directly.
We can wrap the duck class with a count class.
The decoration mode implements an interface, and the method in the interface calls the same method through the same parameter of the variable. For example, in this example, it is the count of ducks quacking, and ++ is called each time.
Adapter design patterns
This example includes several principles:
- First of all, the functions of different interfaces should be separated as much as possible. ISP, that is to say, duck calling and counting should not be written in one method.
- Classes cannot be modified directly, OCP.
- If you want to count duck calls at the same time, just call the wrapper class directly, DRY.
- GooseAdapter only has access to Goose's honk method and not its full access, DIP. If you change it to an inherited subclass here, you will have full access rights.
Wrapper design patterns
Wrapper mode includes decorator and adapter. The decorator mainly means that both the outer wrapper class and the inner class implement an interface, such as the duck quack in the above example. adapter is an inner class and does not need to be implemented.
Immutable View: The problem of java references was mentioned earlier. For example, two variables refer to the same object, and they will be changed once they are changed. This is equivalent to when there is a reference, the target object is completely exposed. In the wrapper, we can restrict the wrapper class: modifying the object is prohibited, and an exception is thrown if the modification is made.
Composite Design Pattern
Wraps a collection.
Observer Pattern
For example, when a car sees a green light, it knows it is time to leave. This kind of observer changes one variable and affects the realization of other variables.
Java provides an observable api, which triggers a function when the value of the corresponding variable changes.
However, this way of writing violates OCP, because we modified dogbot to let him actively implement the update of observer. We can take the decorator design approach.
If dogbots is an interface, dogwatcher can implement the counting function, and can also implement dogbots in files and gui, and implement dogbots in collections. The codes of the two are almost separated.
We first use an ObservableDogBot class to inherit Observable, and implement unfinished dogbots, and then write a dogreporter to implement observer. at lastrover.addObserver(reporter1);
Factory Methods
If we set a dog whose hunger value is greater than 6 to be constructed as greedyDogBot is a subclass of ordinary dog, then both PlainDogBot and greedyDogBot directly provide the construction method is not very good. You can use a construction class to determine what object needs to be returned.
This constructor can return the interface class, but the actual method returns the concrete class that implements the interface class, so that the return class type can be hidden:
The factory class can even wrap the class itself and send back a wrapper class:
Of course, in addition to static factory methods, they can also be non-static factory objects. We can use different factory objects to wrap different wrapper classes, which can further hide some information of the returned object.
For example, in the next example, the spy dog has one more watcher. We initialize two Dog Factories with polymorphic methods, but one is of the actual SpyDogFactory type, and the other is of the actual PlainDogFactory type, so when they call makeDogBot, different dogs will be returned.
For additional packaging functions such as counting, we can also wrap the counting content in the factory class instead of "wrapping the common class with a counting class and then wrapping the counting class with a factory class".
Singleton Design Pattern
The constructor does not necessarily return a newly created object, and the factory class can return an existing object.
Pay attention to the LSP principle.
Object Pool Design Pattern
The object pool pattern keeps a list of objects and returns a specific object when needed.
Strategy Design Pattern
Select a policy to enforce.
The picture above is a function of the dog performing several actions. We can also use the rewritten Comparator to realize the conditional structure, such as comparing how many times the two dogs bark, ab and ab, and make up for the difference if they bark less.
State Design Pattern
The state type of an object can be changed.
The following changed types are the implementation classes of the accountState abstract class, which are initialized in a polymorphic way.
Bridge Design Pattern
Decouple thoughts. For example, if we need brushes of 12 colors, we can choose 12 crayons with fixed colors, or 1 brush and 12 kinds of paints. The brush example decouples brushes and colors well.
Example source: Handling multi-dimensional changes - bridge mode (1)_LoveLion's Blog-CSDN Blog
The following example: find the intersection of father and son.
Flyweight Pattern
Sharing a large number of objects with a lot of internal state and little external state can be shared in a cache-like manner.
Concept source: Intensive reading of "Design Patterns - Flyweight Enjoyment Mode" - Zhihu (zhihu.com)