Hello everyone , I'm Xiaoyu .
The principle or source code of every technology stack we usually use is more or less related to the concept of design patterns , It can also be said that , Only a better grasp of the design pattern , Our ability to code More normative 、 concise , More efficient .
secondly , Design patterns are mostly based on the experience of our predecessors , Standing on the shoulders of giants , Absorb their experience and lessons , Our way of coding will last longer .
meanwhile , During our interview, too Bonus options , If you can tell the interviewer about the design pattern , The interviewer will certainly look at you with new eyes . In the work , Have a good idea of design patterns , It will also be of great help to the development of the project .
Next , Follow Xiaoyu to see what design patterns we need to know ~
Preface
Generally speaking, design patterns are divided into three categories :
_ Create pattern :_ Factory method model 、 Abstract factory pattern 、 The singleton pattern 、 Builder pattern 、 Archetypal model .
_ Structural mode :_ Adapter pattern 、 Decorator mode 、 The proxy pattern 、 Appearance mode 、 Bridging mode 、 Portfolio model 、 The flyweight pattern .
_ Behavioral patterns :_ The strategy pattern 、 Template method pattern 、 Observer mode 、 Iterative subpattern 、 The chain of responsibility model 、 Command mode 、 Memo mode 、 The state pattern 、 Visitor mode 、 Intermediary model 、 Interpreter mode .
The singleton pattern
Concept
Make sure there is only one instance of a class , and self-instantiation And provide the whole system with this example .
Use scenarios
-
The environment that requires a unique serial number to be generated ;
-
A shared access point or shared data is needed throughout the project , For example, one Web Counters on the page , No need to record every refresh to the database , Use singleton mode to keep the counter value , And make sure it's thread safe ;
-
Creating an object consumes too many resources , To access IO And database resources ;
-
A lot of static constants and static methods need to be defined ( Such as tools ) Environment , You can use the singleton mode ( Of course , It can also be declared directly as static The way ).
Code example
Thread safety :
`public class Singleton {`
`private static final Singleton singleton = new Singleton();`
`// Limit the generation of multiple objects `
`private Singleton(){`
`}`
`// Through this method, the instance object is obtained `
`public static Singleton getSingleton(){`
`return singleton;`
`}`
`// Class , Try to be static`
`public static void doSomething(){`
`}`
`}`
Thread unsafe :
`public class Singleton {`
`private static Singleton singleton = null;`
`// Limit the generation of multiple objects `
`private Singleton(){`
`}`
`// Through this method, the instance object is obtained `
`public static Singleton getSingleton(){`
`if(singleton == null){`
`singleton = new Singleton();`
`}`
`return singleton;`
`}`
`}`
Unsafe for threads :
stay getSingleton Methods before adding synchronized keyword , It can also be in getSingleton Add... In the method synchronized To achieve .
Factory mode
Concept
Defines an interface for creating objects , Let the subclass decide which class to instantiate . The factory method makes a class Instantiation delay To its subclasses .
Use scenarios
jdbc Connect to database , Hardware access , Reduce the generation and destruction of objects
structure
_ Simple factory model :_ A module only needs one factory class , There's no need to produce it , Using static methods
_ Multiple factory classes :_ Every race ( Specific product categories ) They all correspond to a Creator , Each creator is responsible for creating the corresponding product object independently , Very consistent with the principle of single responsibility
_ Instead of singleton mode :_ The core requirement of singleton mode is that there is only one object in memory , With the factory method pattern, you can also produce only one object in memory
_ Delay initialization :_ProductFactory Responsible for the creation of product class objects , And through prMap Variable produces a cache , Keep... For objects that need to be reused again
Code example
Product Responsible for defining product commonalities for abstract product classes , Realize the most abstract definition of things ;
Creator Create classes for abstractions , It's the abstract factory , How to create a product class is determined by the implementation factory ConcreteCreator Accomplished .
`public class ConcreteCreator extends Creator {`
`public <T extends Product> T createProduct(Class<T> c){`
`Product product=null;`
`try {`
`product =`
`(Product)Class.forName(c.getName()).newInstance();`
`} catch (Exception e) {`
`// exception handling `
`}`
`return (T)product;`
`}`
`}`
Abstract factory pattern
Concept
Provides an interface for creating a set of related or interdependent objects , and No need to specify their concrete classes .
Use scenarios
A family of objects ( Or a group of unrelated objects ) All have the same constraints .
When it comes to different operating systems , You can consider using the abstract factory pattern .
Code example
`public abstract class AbstractCreator {`
`// establish A Product family `
`public abstract AbstractProductA createProductA();`
`// establish B Product family `
`public abstract AbstractProductB createProductB();`
`}`
Template method pattern
Concept
Define the framework of an algorithm in an operation , Instead, defer some steps to subclasses . So that subclasses can Without changing the structure of an algorithm You can redefine some specific steps of the algorithm .
Use scenarios
-
Multiple subclasses have public methods , And when the logic is basically the same .
-
important 、 Complex algorithms , The core algorithm can be designed as a template method , The peripheral details are implemented by each subclass .
-
Refactoring , Template method pattern is a frequently used pattern , Extract the same code into the parent class , And then through the hook function ( see “ Template method pattern extension ”) Restrain their actions .
structure
Abstract template :AbstractClass
For abstract templates , Its methods fall into two categories :
1、 The basic method : It's also called basic operation , Methods implemented by subclasses , And when the template method is called .
2、 Template method : There can be one or more , It's usually a specific method , It's a framework , Realize the scheduling of basic methods , Complete the fixed logic .
Be careful : In order to prevent malicious operation , General template methods add final
keyword , Overwriting... Is not allowed .
_ Specific template :_ Implement one or more abstract methods defined by the parent class , That is, the basic methods defined by the parent class are implemented in the child class .
Code example
`package templateMethod;`
`public class TemplateMethodPattern`
`{`
`public static void main(String[] args)`
`{`
`AbstractClass tm=new ConcreteClass();`
`tm.TemplateMethod();`
`}`
`}`
`// abstract class `
`abstract class AbstractClass`
`{`
`public void TemplateMethod() // Template method `
`{`
`SpecificMethod();`
`abstractMethod1();`
`abstractMethod2();`
`}`
`public void SpecificMethod() // The specific methods `
`{`
`System.out.println(" Concrete methods in abstract classes are called ...");`
`}`
`public abstract void abstractMethod1(); // Abstract method 1`
`public abstract void abstractMethod2(); // Abstract method 2`
`}`
`// Specific subclass `
`class ConcreteClass extends AbstractClass`
`{`
`public void abstractMethod1()`
`{`
`System.out.println(" Abstract method 1 The implementation of is called ...");`
`}`
`public void abstractMethod2()`
`{`
`System.out.println(" Abstract method 2 The implementation of is called ...");`
`}`
`}`
Builder pattern
Concept
Separate the construction of a complex object from its representation , bring The same build process can create different representations .
Use scenarios
-
Same method , Different order of execution , When different event results are produced , You can use builder mode .
-
Multiple components or parts , Can be assembled into an object , But the results are not the same , You can use this mode .
-
The product category is very complex , Or the different calling order in the product class produces different performance , It's a good time to use builder mode .
structure
_Product Product class :_ The template method pattern is usually implemented , There are template methods and basic methods .
_Builder Abstract builder :_ Standardizing the formation of products , It is usually implemented by subclasses .
_ConcreteBuilder Specific builder :_ Implement all methods defined by an abstract class , And return a group created object .
_Director Directors :_ Responsible for arranging the order of existing modules , Then tell Builder Start building
Code example
`public class ConcreteProduct extends Builder {`
`private Product product = new Product();`
`// Set up product parts `
`public void setPart(){`
`/*`
`* Logical processing within the product class `
`*/`
`}`
`// Build a product `
`public Product buildProduct() {`
`return product;`
`}`
`}`
The proxy pattern
Concept
For other objects Provide a proxy to control Access to this object .
structure
_Subject Abstract theme role :_ Abstract topic classes can be abstract classes or interfaces , Is the most common definition of business type , No special requirements .
_RealSubject Specific subject roles :_ It's also called the delegated role 、 Surrogate role . It's the big loser , Is the concrete executor of business logic .
_Proxy Surrogate subject role :_ It's also called the delegate class 、 proxy class . It's responsible for the application of real characters , Methods that define all abstract topic classes 、 Restrict delegating to real theme role implementations , And do the pre-processing and post-processing work before and after the real theme role processing .
classification
_ General agent :_ In this mode , The caller only knows the agent, not who the real role is , Shielding the influence of real role changes on high-level modules , Real theme characters can be modified as they want , No impact on high-level modules , As long as you implement the method corresponding to the interface , This mode is very suitable for the situation with high scalability requirements .
_ Compulsory agency :_ The concept of mandatory proxy is to find the proxy role from the real role , No direct access to real characters . High level modules just call getProxy You can access all the methods of the real character , It doesn't need to generate a proxy at all , Agent management has been done by real characters themselves .
- difference : General agency means that we need to know the existence of agency , Then we can visit ; Forcing a proxy means that the caller calls the real role directly , It doesn't matter if the agent exists , The generation of its agent is determined by the real role .
_ A dynamic proxy :_ Generate all methods based on the interface being proxied , That is to say, given an interface , Dynamic agents will claim “ I have implemented all the methods under this interface ”. Two independent development lines . Dynamic agent realizes the responsibility of agent , Business logic realizes the related logic functions , There is no necessary coupling relationship between the two . Notice cuts in from another perspective , Finally, coupling in high-level modules , Complete the task of logic encapsulation .
-
Intention : Cross section programming , Enhance or control the behavior of objects without changing our existing code structure .
-
The first condition : The proxy class must implement an interface .
Code example
`public Object getProxy(@Nullable ClassLoader classLoader) {`
`if (logger.isTraceEnabled()) {`
`logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());`
`}`
`Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);`
`findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);`
`return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);`
`}`
Archetypal model
Concept
Using prototype instances to specify the kind of objects to create , also By copying these prototypes Create a new object .
Use scenarios
_ Resource optimization scenarios :_ Class initialization needs to digest a lot of resources , This resource includes data 、 Hardware resources, etc .
_ Performance and security requirements scenarios :_ adopt new Generating an object requires a lot of data preparation or access rights , You can use prototype mode .
_ A scene where an object has multiple modifiers :_ An object needs to be provided for other objects to access , And each caller may need to change its value , Sure 、 Consider using prototype mode to copy multiple objects for callers to use .
advantage
Prototype pattern is actually implementation Cloneable Interface , rewrite clone() Method .
_ Excellent performance :_ The prototype pattern is a copy of the binary stream in memory , More than direct new The performance of an object is much better , Especially when a large number of objects are generated in a cycle , Prototype pattern can better reflect its advantages .
_ Escape the constraints of constructors :_ This is both its advantage and its disadvantage , Copy directly in memory , Constructors don't execute .
Code example
`public class PrototypeClass implements Cloneable{`
`// Override parent Object Method `
`@Override`
`public PrototypeClass clone(){`
`PrototypeClass prototypeClass = null;`
`try {`
`prototypeClass = (PrototypeClass)super.clone();`
`} catch (CloneNotSupportedException e) {`
`// exception handling `
`}`
`return prototypeClass;`
`}`
`}`
Intermediary model
Concept
Encapsulating a series of object interactions with a mediation object , Mediators make objects interact without explicit interaction , To make it Loose coupling , And they can change their interaction independently .
Use scenarios
The mediator pattern is suitable for close coupling between multiple objects , The standard of tight coupling is : There is a spider web structure in the class diagram , That is, each class is directly related to other classes .
structure
_Mediator The role of an abstract intermediary :_ Abstract mediator role defines a unified interface , It is used for communication between colleagues' roles .
_Concrete Mediator Specific intermediary role :_ The specific intermediary role realizes cooperative behavior by coordinating the roles of colleagues , So it has to depend on the role of each colleague .
_Colleague Colleague role :_ Every co-worker role knows the intermediary role , And when communicating with other coworker roles , Be sure to collaborate through the intermediary role . There are two types of behavior for each colleague class : One is the behavior of colleagues themselves , Such as changing the state of the object itself , Dealing with your own behavior, etc , This behavior is called spontaneous behavior (SelfMethod), There is no dependency on other colleagues or mediators ; The second is the behavior that must rely on the intermediary to complete , It's called dependency methods (Dep-Method).
Sample code
`public abstract class Mediator {`
`// Define the colleague class `
`protected ConcreteColleague1 c1;`
`protected ConcreteColleague2 c2;`
`// adopt getter/setter Method to inject the colleague class `
`public ConcreteColleague1 getC1() {`
`return c1;`
`}`
`public void setC1(ConcreteColleague1 c1) {`
`this.c1 = c1;`
`}`
`public ConcreteColleague2 getC2() {`
`return c2;`
`}`
`public void setC2(ConcreteColleague2 c2) {`
`this.c2 = c2;`
`}`
`// The business logic of the mediator model `
`public abstract void doSomething1();`
`public abstract void doSomething2();`
`}`
Command mode
Concept
Encapsulate a request as an object , So you can parameterize the client with different requests , Yes Request queuing or request logging , Can provide command undo and restore function .
Use scenarios
Where you think it's a command, you can use command mode , for example , stay GUI In development , The click of a button is a command , You can use command mode ; simulation DOS When ordered , Of course, command mode should also be adopted ; Trigger - Feedback mechanism, etc .
structure
_Receive Receiver role :_ The role is the role of work , The command passed here should be executed , In our example above, it is Group Three implementation classes of ( Demand group , Art Group , Code group ).
_Command Command character :_ All commands that need to be executed are declared here .
_Invoker The role of the caller :_ Received an order , And execute the command . In the example , I ( project manager ) That's the character .
Code example
`public class Invoker {`
`private Command command;`
`// Set value injection `
`public void setCommand(Command command) {`
`this.command = command;`
`}`
`// Carry out orders `
`public void action() {`
`this.command.execute();`
`}`
`}`
The chain of responsibility model
Concept
Give multiple objects a chance to process requests , This avoids the coupling between the sender and the receiver of the request . Put these objects In a chain , And pass the request along the chain , Until an object processes it .
duty
The abstract processor implements three responsibilities :
1、 Define the processing method of a request handleMessage, The only way to open up ;
2、 Define a chain arrangement setNext, Set up the next handler ;
3、 It defines two methods that a specific requester must implement : Define the level you can handle getHandlerLevel And specific processing tasks echo.
Code example
`public abstract class Handler {`
`private Handler nextHandler;`
`// Every handler has to deal with the request `
`public final Response handleMessage(Request request){`
`Response response = null;`
`// Determine if it's your own processing level `
`if(this.getHandlerLevel().equals(request.getRequestLevel())){`
`response = this.echo(request);`
`}else{ // Not at your own processing level `
`// Determine if there is a next processor `
`if(this.nextHandler != null){`
`response =`
`this.nextHandler.handleMessage(request);`
`}else{`
`// There is no proper handler , The business deals with itself `
`} }`
`return response;`
`}`
`// Set who the next handler is `
`public void setNext(Handler _handler){`
`this.nextHandler = _handler;`
`}`
`// Each processor has a processing level `
`protected abstract Level getHandlerLevel();`
`// Each processor must implement the processing task `
`protected abstract Response echo(Request request);`
`}`
matters needing attention
The number of nodes in the chain needs to be controlled , Avoid super long chains , The general practice is to Handler Set a maximum number of nodes in , stay setNext Method to determine whether it has exceeded its threshold , If it exceeds, the chain is not allowed to establish , Avoid unintentional damage to system performance .
Decoration mode
Concept
Dynamically give an object Add some extra responsibilities . In terms of adding functionality , Decoration patterns are more flexible than subclasses .
Use scenarios
-
Need to extend the function of a class , Or add additional functions to a class .
-
You need to dynamically add functionality to an object , These functions can be revoked dynamically .
-
You need to modify or add features to a group of siblings , Of course, the preferred decoration mode .
structure
_Component Abstract component :_Component It's an interface or an abstract class , It's about defining our core object , That is, the most primitive object . In decorative mode , There must be a fundamental 、 At the core 、 The most primitive interface or abstract class ACTS as Component Abstract component .
_ConcreteComponent The specific components :_ConcreteComponent It's the core 、 The most primitive 、 The most basic interface or abstract class implementation , That's what you're going to decorate .
_Decorator To decorate a character :_ It's usually an abstract class , What's the use of it ? Implementing interfaces or abstract methods , It doesn't have to have abstract methods , There must be one of its attributes private Variable pointing to the Component Abstract component .
_ Specific decorative role :_ Two specific decoration categories , You have to put your core 、 ancestral 、 The most basic things are decorated with other things .
Code example
`/**`
`* To decorate a character `
`*/`
`@Data`
`@AllArgsConstructor`
`@NoArgsConstructor`
`@Log`
`class BufferedReader implements Reader{`
`private Reader reader;`
`@Override`
`public void read() {`
`reader.read();`
`}`
`public void readLine(){`
`read();`
`log.info(" And read only one line ");`
`}`
`}`
The strategy pattern
Concept
Define a set of algorithms , take Every algorithm is encapsulated , And make them interchangeable .
Use scenarios
-
Multiple classes have only slightly different scenarios in algorithm or behavior .
-
The algorithm needs to switch freely .
-
Scenarios that need to mask algorithm rules .
-
The number of specific strategies exceeds 4 individual , You need to consider using hybrid mode
structure
_Context Encapsulate the character :_ It's also called contextual roles , Link between the above and the next packaging role , Shield high-level modules against policies 、 Direct access to the algorithm , Encapsulate possible changes .
_Strategy Abstract strategy roles :_ Strategy 、 The abstraction of algorithm family , Usually interface , Define the methods and properties that each policy or algorithm must have .
_ConcreteStrategy Specific strategic roles :_ Implement operations in abstract strategies , This class contains specific algorithms .
Code example
`public enum Calculator {`
`// Addition operation `
`ADD("+"){`
`public int exec(int a,int b){`
`return a+b;`
`}`
`},`
`// Subtraction `
`SUB("-"){`
`public int exec(int a,int b){`
`return a - b;`
`}`
`};`
`String value = "";`
`// Define member value types `
`private Calculator(String _value){`
`this.value = _value;`
`}`
`// Gets the value of the enumeration member `
`public String getValue(){`
`return this.value;`
`}`
`// Declare an abstract function `
`public abstract int exec(int a,int b);`
`}`
Adapter pattern
Concept
Interface of a class Transform to another interface expected by the client , So that the two classes that could not work together due to interface mismatch can work together .
Use scenarios
When you have an incentive to modify an interface that is already in production , The adapter mode is probably the best for you . For example, the system has expanded , You need to use an existing or newly created class , But this class does not conform to the interface of the system , What do I do ? Don't think about using adapter patterns in the detailed design phase , The main scenario is in the extended application .
The class adapter
_Target The target character :_ This role defines what interfaces the other classes are converted to , That's our expected interface .
_Adaptee The source role :_ Who do you want to turn into the target character , This “ who ” That's the source role , It's already there 、 A well-functioning class or object , Through the packaging of the adapter role , It's going to be a brand new 、 Beautiful characters .
_Adapter Adapter role :_ The core role of the adapter pattern , The other two roles are existing roles , The adapter role needs to be newly created , Its duties are very simple : Converts the source role to the target role , How to convert ? By inheritance or class Association .
Object adapter
Don't use multiple inheritance or inheritance , Instead, use direct correlation , Or the way of delegation .
The difference between object adapter and class adapter :
Class adapters are inter class inheritance , An object adapter is a composite relationship of an object , It can also be said to be the association of classes , This is the fundamental difference between the two . In the actual project, the object adapter uses a relatively large number of scenarios .
Code example
`public class Adapter extends Target`
`{`
`private Adaptee adaptee;`
`public Adapter(Adaptee adaptee)`
`{`
`this.adaptee=adaptee;`
`}`
`public void request()`
`{`
`adaptee.specificRequest();`
`}`
`}`
Iterator pattern
Concept
It provides a way Access elements in a container object , Without exposing the internal details of the object .
structure
_Iterator Abstract iterator :_ Abstract iterators are responsible for defining interfaces to access and traverse elements , And it's basically fixed 3 A way :first() Get the first element ,next() Access the next element ,isDone() Have you visited the bottom (Java be called hasNext() Method ).
_ConcreteIterator Specific iterators :_ The specific iterator role should implement the iterator interface , Complete the traversal of container elements .
_Aggregate Abstract container :_ The container role is responsible for providing an interface to create a specific iterator role , There must be a similar createIterator() This way , stay Java In general iterator() Method .
_Concrete Aggregate Specific containers :_ The concrete container implements the method of container interface definition , Create an object to hold the iterator .
Code example
`/**`
`* Specific iterators `
`*/`
`public class ConcreteIterator<T> implements Iterator<T> {`
`private List<T> list = new ArrayList<>();`
`private int cursor = 0;`
`public boolean hasNext() {`
`return cursor != list.size();`
`}`
`public T next() {`
`T obj = null;`
`if (this.hasNext()) {`
`obj = this.list.get(cursor++);`
`}`
`return obj;`
`}`
`}`
Portfolio model
Concept
Combine objects into a tree structure to represent “ part - whole ” Hierarchical structure , Make the use of single object and composite object consistent .
Use scenarios
-
Maintenance and display part - The whole relationship scenario , Like a tree menu 、 File and folder management .
-
A scenario in which some modules or functions can be separated from the whole .
-
As long as it's a tree structure , Just consider using the composite pattern .
structure
Component Abstract component roles : Define the common methods and properties of the composite objects , You can define some default behaviors or properties .
_Leaf Leaf component :_ Leaf object , There are no other branches under it , The smallest unit of traversal .
_Composite Tree branches :_ Branch object , Its function is to combine branch nodes and leaf nodes to form a tree structure .
Code example
`public class Composite extends Component {`
`// Component containers `
`private ArrayList<Component> componentArrayList = new`
`ArrayList<Component>();`
`// Add a leaf or branch component `
`public void add(Component component){`
`this.componentArrayList.add(component);`
`}`
`// Delete a leaf or branch component `
`public void remove(Component component){`
`this.componentArrayList.remove(component);`
`}`
`// Get all the leaf and branch components under the branch `
`public ArrayList<Component> getChildren(){`
`return this.componentArrayList;`
`}`
`}`
Observer mode
Concept
Define a one to many dependency between objects , Make every time an object changes state , Then all objects that depend on it will Be notified and automatically updated .
Use scenarios
-
Associated behavior scenarios . It should be noted that , Association behavior is divisible , instead of “ Combine ” Relationship .
-
Event multi-level trigger scenario .
-
Cross system message exchange scenario , Such as the processing mechanism of message queue .
structure
_Subject Observed :_ Define the responsibilities that must be fulfilled by the observed , It has to be able to dynamically increase 、 Cancel the observer . It is usually an abstract class or an implementation class , Only fulfill the duties that must be fulfilled as the observed : Manage the observer and inform the observer .
_Observer The observer :_ After the observer receives the message , That is to say update( Update method ) operation , Process the received information .
_ConcreteSubject The specific observed :_ Define the business logic of the observed , It also defines which events are notified .
_ConcreteObserver Specific observer :_ Each observation has a different processing response after receiving the message , Each observer has its own processing logic .
Code example
`public abstract class Subject {`
`// Define an array of observers `
`private Vector<Observer> obsVector = new Vector<Observer>();`
`// Add an observer `
`public void addObserver(Observer o){`
`this.obsVector.add(o);`
`}`
`// Delete an observer `
`public void delObserver(Observer o){`
`this.obsVector.remove(o);`
`}`
`// Notify all observers `
`public void notifyObservers(){`
`for(Observer o:this.obsVector){`
`o.update();`
`}`
`}`
`}`
Facade mode
Concept
The communication between the outside and the inside of a subsystem is required Through a unified object . The facade pattern provides a high-level interface , Makes the subsystem easier to use .
Use scenarios
-
Provide an interface for external access to a complex module or subsystem
-
Subsystem is relatively independent —— The access to the subsystem from the outside world only needs black box operation
-
Prevent the spread of risk from low-level personnel
structure
_Facade The role of the facade :_ The client can call the methods of this role . This role knows all the functions and responsibilities of the subsystem . In general , This role will delegate all requests sent from the client to the corresponding subsystem , In other words, the role has no actual business logic , It's just a delegate class .
_subsystem Subsystem role :_ There can be one or more subsystems at the same time . Each subsystem is not a separate class , It's a collection of classes . The subsystem does not know the presence of facade . For subsystems , Facade is just another client .
Code pattern
`public class Client {`
`// The subsystem object of the delegate `
`private A a= new A();`
`private B b= new B();`
`private C c= new C();`
`// Methods of providing external access `
`public void methodA(){`
`this.a.doSomething();`
`}`
`public void methodB(){`
`this.b.doSomething();`
`}`
`public void methodC(){`
`this.c.doSomething();`
`}`
`}`
Memo mode
Concept
Without breaking encapsulation , Capture the internal state of an object , And save the state outside the object . In this way, the object can be restored to the original saved state later .
Use scenarios
-
Relevant state scenarios that need to save and recover data .
-
Provide a rollback (rollback) The operation of .
-
In the replica scenario that needs to be monitored .
-
The transaction management of database connection is the memo mode .
structure
_Originator Initiator role :_ Record the internal state of the current moment , Responsible for defining which States belong to the backup scope , Responsible for creating and restoring memo data .
_Memento Memo role :_ Responsible for the storage Originator The internal state of the originator object , Provide the internal state the sponsor needs when needed .
_Caretaker Memo administrator role :_ Manage memos 、 Keep and provide memos .
Code example
`public class BeanUtils {`
`// hold bean Put all the attributes and values of into Hashmap in `
`public static HashMap<String,Object> backupProp(Object bean){`
`HashMap<String,Object> result = new`
`HashMap<String,Object>();`
`try {`
`// get Bean describe `
`BeanInfo`
`beanInfo=Introspector.getBeanInfo(bean.getClass());`
`// Get the property description `
`PropertyDescriptor[]`
`descriptors=beanInfo.getPropertyDescriptors();`
`// Traverse all properties `
`for(PropertyDescriptor des:descriptors){`
`// The attribute name `
`String fieldName = des.getName();`
`// Methods to read properties `
`Method getter = des.getReadMethod();`
`// Read property values `
`Object fieldValue=getter.invoke(bean,new`
`Object[]{});`
`if(!fieldName.equalsIgnoreCase("class")){`
`result.put(fieldName, fieldValue);`
`} } } catch (Exception e) {`
`// exception handling `
`}`
`return result;`
`}`
`// hold HashMap The value of is returned to bean in `
`public static void restoreProp(Object bean,HashMap<String,Object>`
`propMap){`
`try {`
`// get Bean describe `
`BeanInfo beanInfo =`
`Introspector.getBeanInfo(bean.getClass());`
`// Get the property description `
`PropertyDescriptor[] descriptors =`
`beanInfo.getPropertyDescriptors();`
`// Traverse all properties `
`for(PropertyDescriptor des:descriptors){`
`// The attribute name `
`String fieldName = des.getName();`
`// If you have this property `
`if(propMap.containsKey(fieldName)){`
`// The way to write properties `
`Method setter = des.getWriteMethod();`
`setter.invoke(bean, new`
`Object[]{propMap.get(fieldName)});`
`} } } catch (Exception e) {`
`// exception handling `
`System.out.println("shit");`
`e.printStackTrace();`
`}`
`}`
`}`
Visitor mode
Concept
Package some Operations that act on the elements of a data structure , It can define new operations on these elements without changing the data structure .
Use scenarios
-
An object structure contains many class objects , They have different interfaces , And you want to do something with these objects that depends on their specific classes , In other words, it's a situation that can't be competent with iterator mode .
-
Many different and unrelated operations need to be performed on the objects in an object structure , And you want to avoid having these operations “ Pollution ” Classes for these objects .
structure
_Visitor—— Abstract Visitor :_ Abstract class or interface , Declare which elements visitors can access , To be specific to the procedure is visit The parameters of the method define which objects can be accessed .
_ConcreteVisitor—— Specific visitors :_ It affects what visitors do when they visit a class , What are you going to do .
_Element—— Abstract elements :_ Interface or abstract class , State what kind of visitors are allowed to visit , The procedure is through accept Method .
_ConcreteElement—— Specific elements :_ Realization accept Method , Usually visitor.visit(this), Basically, a pattern has been formed .
_ObjectStruture—— The structure of the object :_ The element producer , Generally, it can be accommodated in many different types 、 Containers with different interfaces , Such as List、Set、Map etc. , In the project , This character is rarely abstracted .
Code example
`public class CompensationVisitor implements Visitor {`
`@Override`
`public void Visit(Element element) {`
`// TODO Auto-generated method stub`
`Employee employee = ((Employee) element);`
`System.out.println(`
`employee.getName() + "'s Compensation is " + (employee.getDegree() * employee.getVacationDays() * 10));`
`}`
`}`
The state pattern
Concept
Be an object When the inner state changes, allow it to change behavior , This object looks like it changed its class .
Use scenarios
-
A scene in which behavior changes as states change , This is also the starting point of the model , For example, permission design , The state of people is different, even if they perform the same behavior, the results will be different , In this case, you need to consider using state patterns .
-
Conditions 、 A substitute for a branch judgment statement
structure
_State—— Abstract state role :_ Interface or abstract class , Responsible for object state definition , And encapsulate the role of the environment to achieve state switching .
_ConcreteState—— Specific status role :_ Each specific state must fulfill two responsibilities : Behavior management of this state and trend state processing , In layman's terms , It's what we have to do in this state , And how this state transitions to other states .
_Context—— Environmental roles :_ Define the interface required by the client , And responsible for the specific state switching .
Code example
`// Abstract state role `
`public abstract class State {`
`// Define an environmental role , Provide subclass access to `
`protected Context context;`
`// Setting up environment roles `
`public void setContext(Context _context){`
`this.context = _context;`
`}`
`// Behavior 1`
`public abstract void handle1();`
`// Behavior 2`
`public abstract void handle2();`
`}`
Interpreter mode
Concept
Give a language , A representation of the grammar that defines it , And define an interpreter , The interpreter Use this representation to explain sentences in a language .
Use scenarios
-
Recurring problems can use interpreter mode
-
A simple grammar needs to explain the scene
structure
_AbstractExpression—— abstract interpreter :_ The specific interpretation task is completed by each implementation class , The specific interpreter is composed of TerminalExpression and Non-terminalExpression complete .
_TerminalExpression—— Terminator expression :_ Implement the interpretation operations associated with elements in grammar , Usually there is only one terminator expression in an Interpreter pattern , But there are multiple instances , Corresponding to different terminators .
_NonterminalExpression—— Nonterminal expression :_ Each rule in grammar corresponds to a non terminal expression , Nonterminal expressions increase based on the complexity of the logic , In principle, each grammar rule corresponds to a nonterminal expression .
_Context—— Environmental roles :_ In general, it is used to store the specific value corresponding to each terminator in grammar , This information needs to be stored in environmental roles , In many cases, we use Map It's enough to play an environmental role .
Code example
`/**`
`* Terminator expression `
`*/`
`public class TerminalExpression extends AbstractExpression {`
`@Override`
`public void interpret(Context ctx) {`
`// Implements the interpretation operation associated with the terminator in the grammar rule `
`}`
`}`
`/**`
`* Nonterminal expression `
`*/`
`public class NonterminalExpression extends AbstractExpression {`
`@Override`
`public void interpret(Context ctx) {`
`// Implement the interpretation operation associated with the non terminal character in the grammar rule `
`}`
`}`
The flyweight pattern
Concept
Using shared objects can effectively Supports a large number of fine-grained objects .
Object information is divided into two parts : Internal state (intrinsic) And the external state (extrinsic).
_ Internal state :_ Internal state is the information that an object can share , It is stored inside the enjoy object and does not change with the environment .
_ External state :_ An external state is a token that an object can depend on , It changes with the environment 、 Unshareable state .
Use scenarios
-
There are a large number of similar objects in the system .
-
Fine-grained objects have a similar external state , And the internal state is independent of the environment , That is, the object has no specific identity .
-
Scenarios where a buffer pool is required .
structure
_Flyweight—— Abstract meta roles :_ It is simply an abstract class of a product , An interface or implementation that defines both the external and internal state of an object .
_ConcreteFlyweight—— Specific enjoy yuan role :_ A specific product class , Implement the business of abstract role definition . It's important to note in this role that internal state processing should be environment independent , There shouldn't be an operation that changes the internal state , The external state was also modified , This is absolutely not allowed .
_unsharedConcreteFlyweight—— Shareable role :_ There are no external states or security requirements ( Such as thread safety ) Objects that can't be shared , This object does not normally appear in the Heyuan factory .
_FlyweightFactory—— The flyweight factory :_ The duties are very simple , That is to construct a pool container , It also provides methods to get objects from the pool .
Code example
`public class FlyweightFactory {`
`// Define a pool container `
`private static HashMap<String,Flyweight> pool= new`
`HashMap<String,Flyweight>();`
`// The flyweight factory `
`public static Flyweight getFlyweight(String Extrinsic){`
`// The object that needs to be returned `
`Flyweight flyweight = null;`
`// There is no object in the pool `
`if(pool.containsKey(Extrinsic)){`
`flyweight = pool.get(Extrinsic);`
`}else{`
`// Create a share object based on the external state `
`flyweight = new ConcreteFlyweight1(Extrinsic);`
`// Put it in the pool `
`pool.put(Extrinsic, flyweight);`
`}`
`return flyweight;`
`}`
`}`
Bridge mode
Concept
take Abstraction and implementation decoupling , So that the two can change independently .
Use scenarios
-
Scenarios where inheritance is not expected or applicable
-
Unstable interface or class abstraction
-
Scenarios that require high reusability
structure
_Abstraction—— Abstract character :_ Its main responsibility is to define the behavior of the character , Also save a reference to the implemented role , The role is generally an abstract class .
_Implementor—— Realize the role :_ It's an interface or an abstract class , Define the necessary behaviors and attributes of a character .
_RefinedAbstraction—— Fixed abstract character :_ It refers to the implementation role to modify the abstract role .
_ConcreteImplementor—— Concrete realization role :_ It implements methods and properties defined by interfaces or abstract classes .
Code example
`public abstract class Abstraction {`
`// Define a reference to an implemented role `
`private Implementor imp;`
`// The constraint subclass must implement the constructor `
`public Abstraction(Implementor _imp){`
`this.imp = _imp;`
`}`
`// Their own behavior and attributes `
`public void request(){`
`this.imp.doSomething();`
`}`
`// Get realized roles `
`public Implementor getImp(){`
`return imp;`
`}`
`}`
summary
When you're learning design patterns , Don't make it hard , in the final analysis , It's a summary of some generalities . We need to study and work constantly at ordinary times , Take time to understand its underlying principles , In this way, each design pattern can be applied flexibly .
The design pattern is based on the summary of predecessors , A solution to the problems in some scenarios , Design patterns are not formulas , There's no need to memorize every pattern , It's more important to understand it Abstract ideas , And how application design patterns Better problem solving , What can be achieved . There are many theories , But if we want to master it , For our actual development, it will solve many problems .
Of course, we will continue to update about Design principles The content of , It is convenient for you to further understand the design pattern .