The principle or source code of each technology stack we usually use is more or less related to the concept of design pattern. It can also be said that only by better mastering the design pattern, our code can be more standardized, concise and more efficient.
Secondly, most of the design patterns are repeatedly summarized by the experience of our predecessors. Standing on the shoulders of giants and absorbing their experience and lessons, our coding road will last longer.
At the same time, it is also a plus point option in our interview process. If you can tell the design pattern to the interviewer, the interviewer will certainly look at you with new eyes. In the work, having a good design pattern idea 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:
Creation mode: factory method mode, abstract factory mode, singleton mode, builder mode and prototype mode.
Structural mode: adapter mode, decorator mode, agent mode, appearance mode, bridge mode, combination mode and sharing mode.
Behavioral mode: strategy mode, template method mode, observer mode, iteration sub mode, responsibility chain mode, command mode, memo mode, status mode, visitor mode, mediator mode and interpreter mode.
Singleton mode
concept
Ensure that a class has only one instance, and instantiate it by itself and provide this instance to the whole system.
Usage scenario
-
Environment requiring the generation of unique serial number;
-
In the whole project, a shared access point or shared data is required, such as the counter on a Web page. You can use the singleton mode to maintain the value of the counter and ensure thread safety without recording each refresh in the database;
-
Creating an object consumes too many resources, such as accessing IO, database and other resources;
-
The environment that needs to define a large number of static constants and static methods (such as tool classes) can adopt the singleton mode (of course, it can also be declared as static directly).
Code example
Thread safety:
public class Singleton { private static final Singleton singleton = new Singleton(); //Limit the generation of multiple objects private Singleton(){ } //The instance object is obtained by this method public static Singleton getSingleton(){ return singleton; } //Other methods in the class should be static as far as possible public static void doSomething(){ } }
public class Singleton { private static Singleton singleton = null; //Limit the generation of multiple objects private Singleton(){ } //The instance object is obtained by this method public static Singleton getSingleton(){ if(singleton == null){ singleton = new Singleton(); } return singleton; } }
Unsafe for threads:
Add the synchronized keyword before the getSingleton method, or add synchronized in the getSingleton method.
Factory mode
concept
Define an interface for creating objects and let subclasses decide which class to instantiate. Factory methods delay the instantiation of a class to its subclasses.
Usage scenario
jdbc connection database, hardware access, reduce the generation and destruction of objects
structure
Simple factory mode: a module only needs one factory class. There is no need to generate it and use static methods
Multiple factory classes: each race (specific product class) corresponds to a creator. Each creator is independently responsible for creating the corresponding product object, which is 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, and only one object can be produced in memory through factory method mode
Delayed initialization: ProductFactory is responsible for the creation of product class objects, and generates a cache through the prMap variable to retain objects that need to be reused again
Code example
Product is an abstract product class, which is responsible for defining the commonness of products and realizing the most abstract definition of things;
Creator creates a class for abstraction, that is, an abstract factory. How to create a product class is completed by the concrete implementation factory ConcreteCreator.
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; } }
concept
Provides an interface for creating a set of related or interdependent objects without specifying their specific classes.
Usage scenario
An object family (or a group of objects that have no relationship) has the same constraints.
When it comes to different operating systems, you can consider using the abstract factory pattern.
Code example
public abstract class AbstractCreator { //Create A product family public abstract AbstractProductA createProductA(); //Create family B products public abstract AbstractProductB createProductB(); }
concept
Define the framework of an algorithm in operation, and delay some steps to subclasses. The subclass can redefine some specific steps of an algorithm without changing the structure of the algorithm.
Usage scenario
-
When multiple subclasses have public methods and the logic is basically the same.
-
For important and complex algorithms, the core algorithm can be designed as a template method, and the surrounding detailed functions are realized by each subclass.
-
During refactoring, the template method pattern is a frequently used pattern. Extract the same code into the parent class, and then restrict its behavior through hook functions (see "extension of template method pattern").
structure
Abstract template: AbstractClass is an abstract template. Its methods are divided into two categories:
1. Basic method: also called basic operation, it is a method implemented by subclasses and called in template methods.
2. Template method: there can be one or several, generally a specific method, that is, a framework to realize the scheduling of basic methods and complete fixed logic.
Note: in order to prevent malicious operations, the keyword "final" is added to the general template method, which is not allowed to be overwritten.
Concrete template: implement one or more abstract methods defined by the parent class, that is, the basic methods defined by the parent class can be 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() //Specific method { 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("The implementation of abstract method 1 is called..."); } public void abstractMethod2() { System.out.println("The implementation of abstract method 2 is called..."); } }
concept
Separate the construction of a complex object from its representation, so that the same construction process can create different representations.
Usage scenario
-
When the same method, different execution sequences and different event results are generated, the builder mode can be adopted.
-
Multiple assemblies or parts can be assembled into one object, but the running results are different, you can use this mode.
-
The product class is very complex, or the calling order in the product class is different, resulting in different efficiency. At this time, it is very appropriate to use the builder mode.
structure
Product class: it usually implements the template method pattern, that is, there are template methods and basic methods.
Builder Abstract Builder: the establishment of standardized products is generally realized by subclasses.
Concrete Builder: implement all methods defined by the abstract class and return a group of built objects.
Director class: responsible for arranging the order of existing modules, and then telling Builder to start construction
Code example
public class ConcreteProduct extends Builder { private Product product = new Product(); //Set up product parts public void setPart(){ /* * Logical processing in product class */ } //Build a product public Product buildProduct() { return product; } }
concept
Provide a proxy for other objects to control access to this object.
structure
Subject abstract topic role: the abstract topic class can be either an abstract class or an interface. It is the most common business type definition without special requirements.
RealSubject specific subject role: also called delegated role and delegated role. It is the head of injustice and the specific executor of business logic.
Proxy subject role: also called delegate class and proxy class. It is responsible for the application of real roles, delegating the methods and restrictions defined by all abstract topic classes to the implementation of real topic roles, and doing pre-processing and post-processing before and after the processing of real topic roles.
classification
General agent: in this mode, the caller only knows the agent without knowing who the real role is. It shields the impact of the change of the real role on the high-level module. The real subject role can be modified as it wants. It has no impact on the high-level module. As long as you implement the method corresponding to the interface, This mode is very suitable for occasions requiring high scalability.
Forced proxy: the concept of forced proxy is to find the proxy role from the real role. Direct access to the real role is not allowed. As long as the high-level module calls getProxy, it can access all the methods of the real role. It doesn't need to generate a proxy at all. The management of the proxy has been completed by the real role itself.
-
Difference: general agent is that we need to know the existence of the agent before we can access it; Forced agent is that the caller directly calls the real role without caring about whether the agent exists. The generation of the agent is determined by the real role.
Dynamic proxy: generate all methods according to the proxy interface, that is, given an interface, the dynamic proxy will declare that "I have implemented all methods under this interface". Two independent development lines. The dynamic agent realizes the responsibility of the agent, and the business logic realizes the relevant logical functions. There is no inevitable coupling relationship between the two. The notification cuts in from another aspect, and finally couples in the high-level module to complete the logical encapsulation task.
-
Intent: cross-sectional programming to enhance or control the behavior of objects without changing our existing code structure.
-
First condition: the proxied 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); }
concept
Specify the type of objects to be created with prototype instances, and create new objects by copying these prototypes.
Usage scenario
Resource optimization scenario: class initialization needs to digest a lot of resources, including data, hardware resources, etc.
Scenario of performance and security requirements: if generating an object through new requires very cumbersome data preparation or access rights, you can use the prototype mode.
A scene where an object has multiple modifiers: when an object needs to be accessed by other objects, and each caller may need to modify its value, you can and consider using the prototype mode to copy multiple objects for the caller.
advantage
The prototype pattern is actually to implement the clonable interface and rewrite the clone () method.
Excellent performance: the prototype mode is a copy of the binary stream in memory, which is much better than directly new an object. Especially when a large number of objects are generated in a loop, the prototype mode can better reflect its advantages.
Escape the constraints of the constructor: This is both its advantages and disadvantages. If it is copied directly in memory, the constructor will not be executed.
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; } }
concept
Using a mediation object to encapsulate a series of object interactions, the mediator makes the objects interact without display, so that their coupling is loose, and the interaction between them can be changed independently.
Usage scenario
The mediator pattern is applicable to the tight coupling between multiple objects. The standard of tight coupling is that there is a spider web structure in the class diagram, that is, each class is directly related to other classes.
structure
Mediator Abstract mediator role: the abstract mediator role defines a unified interface for communication between colleague roles.
Concrete Mediator role: the Concrete Mediator role realizes cooperative behavior by coordinating the roles of colleagues, so it must rely on the roles of colleagues.
Collague Colleague role: every Colleague role knows the intermediary role, and when communicating with other Colleague roles, we must cooperate through the intermediary role. Each Colleague's behavior is divided into two types: one is the behavior of the Colleague itself, such as changing the state of the object itself and dealing with his own behavior. This behavior is called self method, which has no dependence on other colleagues or intermediaries; The second is the behavior that must rely on intermediaries to complete, which is called dep method.
Sample code
public abstract class Mediator { //Define colleague class protected ConcreteColleague1 c1; protected ConcreteColleague2 c2; //Inject the colleague class through the getter/setter method 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; } //Business logic of intermediary model public abstract void doSomething1(); public abstract void doSomething2(); }
concept
Encapsulate a request into an object, so that you can parameterize the client with different requests, queue the requests or record the request log, which can provide the function of command revocation and recovery.
Usage scenario
The command mode can be adopted where it is considered as a command. For example, in GUI development, the click of a button is a command, and the command mode can be adopted; When simulating DOS commands, of course, the command mode should also be adopted; Processing of trigger feedback mechanism, etc.
structure
Receive receiver role: this role is the role of working. Commands should be executed when they are passed here. Specifically, in our above example, there are three implementation classes of Group (requirement Group, art Group and code Group).
Command role: all commands to be executed are declared here.
Invoker caller role: receives a command and executes it. In the example, I (Project Manager) is this role.
Code example
public class Invoker { private Command command; // Set point injection public void setCommand(Command command) { this.command = command; } // Execute command public void action() { this.command.execute(); } }
concept
Multiple objects have the opportunity to process the request, thus avoiding the coupling relationship between the sender and receiver of the request. Connect these objects into a chain and pass the request along the chain until an object processes it.
duty
The abstract handler implements three responsibilities:
1. Define a request processing method handleMessage, which is the only method open to the public;
2. Define the arrangement method setNext of a chain and set the next handler;
3. It defines two methods that the specific requester must implement: defining the level that he can handle, getHandlerLevel, and the specific processing task echo.
Code example
public abstract class Handler { private Handler nextHandler; //Each handler must process the request public final Response handleMessage(Request request){ Response response = null; //Determine whether it is your own processing level if(this.getHandlerLevel().equals(request.getRequestLevel())){ response = this.echo(request); }else{ //Processing level that does not belong to itself //Determine whether there is a next handler if(this.nextHandler != null){ response = this.nextHandler.handleMessage(request); }else{ //If there is no proper handler, the business will be handled by itself } } return response; } //Set who is the next processor 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); }
The number of nodes in the chain needs to be controlled to avoid the situation of super long chain. The general practice is to set a maximum number of nodes in the Handler and judge whether it has exceeded its threshold in the setNext method. If it exceeds, the chain is not allowed to be established to avoid unintentional destruction of system performance.
Decoration mode
concept
Dynamically add some additional responsibilities to an object. In terms of adding functions, decoration mode is more flexible than generating subclasses.
Usage scenario
-
You need to extend the function of a class or add additional functions to a class.
-
You need to dynamically add functions to an object, and these functions can be dynamically revoked.
-
It is necessary to refit or add functions for a batch of brothers. Of course, it is the preferred decoration mode.
structure
Component abstract component: component is an interface or abstract class, which defines our core object, that is, the most primitive object. In the decoration mode, there must be a most basic, core and primitive interface or abstract class to act as the abstract component of the component.
Concrete component: concrete component is the implementation of the most core, primitive and basic interface or abstract class. What you want to decorate is it.
Decorator decorative role: it is generally an abstract class. What is it used for? Implement interfaces or abstract methods. There may not be abstract methods in them. There must be a private variable in its properties that points to the Component abstract Component.
Specific decorative roles: two specific decorative categories. You should decorate your most core, primitive and basic things into other things.
Code example
/** * Decorative role */ @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"); } }
concept
Define a set of algorithms, encapsulate each algorithm and make them interchangeable.
Usage scenario
-
Multiple classes have only slightly different scenarios in algorithm or behavior.
-
The algorithm needs to switch freely.
-
Scenarios that need to mask algorithm rules.
-
If the number of specific strategies exceeds 4, the mixed mode should be considered
structure
Context encapsulation role: it is also called context role, which serves as a connecting link between the preceding and the following, shields the direct access of high-level modules to policies and algorithms, and encapsulates possible changes.
Strategy Abstract policy role: the abstraction of policy and algorithm family, usually an interface, which defines the methods and attributes that each policy or algorithm must have.
ConcreteStrategy specific policy role: implement the operations in the abstract policy. This class contains specific algorithms.
Code example
public enum Calculator { //Addition operation ADD("+"){ public int exec(int a,int b){ return a+b; } }, //Subtraction operation 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); }
concept
The interface of a class is transformed into another interface expected by the client, so that the two classes that cannot work together due to interface mismatch can work together.
Usage scenario
When you are motivated to modify an interface that is already in production, the adapter mode may be the best mode for you. For example, when the system is extended, it needs to use an existing or newly established class, but this class does not conform to the system interface. What should I do? The adapter mode should not be considered in the detailed design stage. The main scenario is in the extended application.
Class Adapter
Target role: this role defines what kind of interface to convert other classes, that is, our expected interface.
Adaptee source role: the "who" you want to convert into the target role is the source role. It is an existing and well functioning class or object. After being wrapped by the adapter role, it will become a new and beautiful role.
Adapter role: the core role of the adapter pattern. The other two roles are existing roles. The adapter role needs to be newly established. Its responsibilities are very simple: how to convert the source role to the target role? Through inheritance or class association.
object adapter
Instead of multiple inheritance or inheritance, use direct association, or delegate.
Differences between object adapter and class adapter:
Class adapter is the inheritance between classes, and object adapter is the composition relationship of objects, or the association relationship of classes, which is the fundamental difference between the two. In the actual project, there are relatively many scenes used by the object adapter.
Code example
public class Adapter extends Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee=adaptee; } public void request() { adaptee.specificRequest(); } }
concept
It provides a way to access each element in a container object without exposing the internal details of the object.
structure
Iterator Abstract iterator: the abstract iterator is responsible for defining the interface for accessing and traversing elements, and basically has three fixed methods: first() obtains the first element, next() accesses the next element, and isDone() whether it has accessed the bottom (Java is called hasNext(www.sgqccy.com) method).
ConcreteIterator specific iterator: the specific iterator role should implement the iterator interface and complete the traversal of container elements.
Aggregate Abstract container: the container role is responsible for providing an interface to create a specific iterator role. It must provide a method like createIterator(), which is generally iterator() in Java.
Concrete Aggregate concrete container: the concrete container implements the method defined by the container interface and creates the object containing the iterator.
Code example
/** * Concrete iterator */ 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; } }
concept
The objects are combined into a tree structure to represent the hierarchical structure of "part whole", so that users have consistency in the use of single objects and combined objects.
Usage scenario
-
Maintenance and presentation of part overall relationship scenarios, such as tree menu, file and folder management.
-
A scene in which some modules or functions can be separated from a whole.
-
As long as it is a tree structure, consider using a composite pattern.
structure
Component abstract component role: define the common methods and properties of the objects participating in the composition, and you can define some default behaviors or properties.
Leaf component: leaf object, under which there are no other branches, that is, the smallest unit of traversal.
Composite branch component: 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 container private ArrayList<Component> componentArrayList = new ArrayList<Component>(); //Add a leaf component or a 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); } //Obtain all 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, so that whenever an object changes state, all objects that depend on it will be notified and updated automatically.
Usage scenario
-
Associate behavior scenarios. It should be noted that the association behavior is separable, not a "composite" relationship.
-
Event multi-level trigger scenario.
-
Cross system message exchange scenarios, such as the processing mechanism of message queue.
structure
Subject observed: defines the responsibilities that the observed must fulfill. It must be able to dynamically add and cancel observers. It is generally an abstract class or an implementation class, which only performs the duties that must be implemented as an observer: managing the observer and notifying the observer.
Observer Observer: after receiving the message, the observer performs the update operation to process the received information.
ConcreteSubject: defines the business logic of the observed and the events to be notified.
ConcreteObserver specific observers: the processing response of each observer after receiving the message is different, and 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(www.sg170000.com); } } }
concept
It is required that the external and internal communication of a subsystem must be carried out through a unified object. Facade mode provides a high-level interface, which makes the subsystem easier to use.
Usage scenario
-
Provide an external access interface for a complex module or subsystem
-
The subsystem is relatively independent - the external access to the subsystem can only be operated in a black box
-
Prevent the risk spread caused by low-level personnel
structure
Facade facade role: the client can call the method of this role. This role is aware of all functions and responsibilities of the subsystem. Generally, this role will delegate all requests sent from the client to the corresponding subsystem, that is to say, this role has no actual business logic and is 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, but a collection of classes. The subsystem does not know the existence of the facade. For the subsystem, the facade is just another client.
Code mode
public class Client { //Delegated subsystem object 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(); } }
concept
Without breaking the 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.
Usage scenario
-
Relevant state scenarios that need to save and restore data.
-
Provides a rollback operation.
-
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 status at the current time, define the status within the backup scope, and create and restore memo data.
Memento memo role: responsible for storing the internal state of the Originator initiator object and providing the internal state required by the initiator when necessary.
Caretaker memo administrator role: manage, save and provide memos.
Code example
public class BeanUtils { //Put all the attributes and values of the bean into the Hashmap public static HashMap<String,Object> backupProp(Object bean){ HashMap<String,Object> result = new HashMap<String,Object>(); try { //Get Bean description BeanInfo beanInfo=Introspector.getBeanInfo(bean.getClass()); //Get attribute description PropertyDescriptor[] descriptors=beanInfo.getPropertyDescriptors(); //Traverse all attributes for(PropertyDescriptor des:descriptors){ //Attribute name String fieldName = des.getName(); //Method of reading properties Method getter = des.getReadMethod(); //Read attribute value Object fieldValue=getter.invoke(bean,new Object[]{}); if(!fieldName.equalsIgnoreCase("class")){ result.put(fieldName, fieldValue); } } } catch (Exception e) { //exception handling } return result; } //Return the HashMap value to the bean public static void restoreProp(Object bean,HashMap<String,Object> propMap){ try { //Get Bean description BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); //Get attribute description PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); //Traverse all attributes for(PropertyDescriptor des:descriptors){ //Attribute name String fieldName = des.getName(); //If you have this attribute if(propMap.containsKey(fieldName)){ //Method of writing attributes 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
Encapsulates some operations that act on each element in a data structure. It can define new operations that act on these elements without changing the data structure.
Usage scenario
-
An object structure contains many class objects, which have different interfaces, and you want to implement some operations on these objects that depend on their specific classes, that is to say, it is a situation where iterator mode is no longer competent.
-
You need to perform many different and irrelevant operations on objects in an object structure, and you want to avoid making these operations "pollute" the classes of these objects.
structure
Visitor - Abstract visitor: an abstract class or interface that declares which elements the visitor can access. Specifically, the parameters of the visit method define which objects can be accessed.
ConcreteVisitor - specific visitor: it affects what visitors should do and do after accessing a class.
Element - abstract element: an interface or abstract class that declares which type of visitor to accept. It is defined programmatically through the parameters in the accept method.
ConcreteElement -- concrete element: implement the accept method, usually visitor Visit (this) has basically formed a model.
ObjectStruture - structure object: the element generator is generally contained in multiple containers with different types and interfaces, such as List, Set, Map, etc. in the project, this role 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)); } }
concept
When an object's internal state changes, it is allowed to change its behavior. The object looks like it has changed its class.
Usage scenario
-
This is also the fundamental starting point of the state mode. For example, the status of permission designers will be different even if they execute the same behavior. In this case, it is necessary to consider using the state mode.
-
Substitutes for conditional and branch judgment statements
structure
State -- abstract state role: an interface or abstract class, which is responsible for defining the object state and encapsulating the environment role to realize state switching.
ConcreteState - specific state role: each specific state must complete two responsibilities: behavior management and trend state processing of this state, which is what to do in this state and how to transition from this state to other states.
Context - environment role: defines the interface required by the client and is responsible for the switching of specific states.
Code example
//Abstract state role public abstract class State { //Define an environment role to provide subclass access protected Context context; //Setting environment roles public void setContext(Context _context){ this.context = _context; } //Behavior 1 public abstract void handle1(); //Behavior 2 public abstract void handle2(); }
concept
Given a language, define a representation of its grammar and define an interpreter that uses the representation to interpret sentences in the language.
Usage scenario
-
The problem interpreter can be used repeatedly
-
A simple syntax needs to be explained
structure
AbstractExpression - Abstract interpreter: the specific interpretation task is completed by each implementation class, and the specific interpreter is completed by TerminalExpression and non TerminalExpression respectively.
TerminalExpression -- terminator expression: it implements the interpretation operation associated with the elements in the grammar. Usually, there is only one terminator expression in an interpreter mode, but there are multiple instances corresponding to different terminators.
Nonterminal expression -- nonterminal expression: each rule in grammar corresponds to a nonterminal expression, which increases according to the complexity of logic. In principle, each grammar rule corresponds to a nonterminal expression.
Context - environment role: it is generally used to store the specific values corresponding to each terminator in the grammar. This information needs to be stored in the environment role. In many cases, it is enough for us to use Map to act as the environment role.
Code example
/** * Terminator expression */ public class TerminalExpression extends AbstractExpression { @Override public void interpret(Context ctx) { // Implement the interpretation operation associated with the terminator in the syntax rule } } /** * Non terminator expression */ public class NonterminalExpression extends AbstractExpression { @Override public void interpret(Context ctx) { // Implements interpretation operations associated with non terminators in syntax rules } }
Sharing mode
concept
Using shared objects can effectively support a large number of fine-grained objects.
The information of an object is divided into two parts: internal state and external state.
Internal state: the internal state is the information that can be shared by the object. It is stored in the shared meta object and will not change with the environment.
External state: an external state is a mark that an object can rely on. It is a state that changes with the environment and cannot be shared.
Usage scenario
-
There are a large number of similar objects in the system.
-
Fine grained objects have close external states, and the internal state is independent of the environment, that is, the object has no specific identity.
-
Scenarios that require buffer pools.
structure
Flyweight - Abstract meta role: it is simply an abstract class of a product, which defines the interface or implementation of the external state and internal state of the object at the same time.
ConcreteFlyweight - specific meta role: a specific product class that implements the business defined by the abstract role. In this role, it should be noted that the internal state processing should be independent of the environment. There should be no operation that changes the internal state and modifies the external state at the same time, which is absolutely not allowed.
unsharedConcreteFlyweight - unsharable shareable shareable roles: objects that have no external state or security requirements (such as thread safety) and cannot use sharing technology. Generally, this object will not appear in the shareable factory.
FlyweightFactory - enjoy meta factory: the responsibility is very simple. It is to construct a pool container and provide methods to obtain objects from the pool.
Code example
public class FlyweightFactory { //Define a pool container private static HashMap<String,Flyweight> pool= new HashMap<String,Flyweight>(); //Xiangyuan factory public static Flyweight getFlyweight(String Extrinsic){ //Object to return Flyweight flyweight = null; //The object does not exist in the pool if(pool.containsKey(Extrinsic)){ flyweight = pool.get(Extrinsic); }else{ //Create meta objects based on external state flyweight = new ConcreteFlyweight1(Extrinsic); //Place in pool pool.put(Extrinsic, flyweight); } return flyweight; } }
concept
Decouple abstraction and implementation so that they can change independently.
Usage scenario
-
Scenarios where inheritance is not desired or applicable
-
Scenarios where interfaces or abstract classes are unstable
-
Scenarios requiring high reusability
structure
Abstraction - Abstract role: its main responsibility is to define the behavior of the role and save a reference to the implementation role, which is generally an abstract class.
Implementer -- implement a role: it is an interface or abstract class that defines the necessary behaviors and properties of a role.
RefinedAbstraction -- modify the abstract role: it refers to the implementation role to modify the abstract role.
Concreteimplementer -- concrete implementation role: it implements methods and properties defined by an interface or abstract class.
Code example
public abstract class Abstraction { //Defines a reference to an implementation role private Implementor imp; //Constraint subclasses must implement this constructor public Abstraction(Implementor _imp){ this.imp = _imp; } //Own behavior and attributes public void request(){ this.imp.doSomething(); } //Get realized roles public Implementor getImp(){ return imp; } }
summary
When we study design patterns, we should not see how difficult it is. In the final analysis, it is an introductory summary. We need to understand its deep principle slowly in our daily continuous study and work, so as to flexibly apply each design mode.
Design pattern is a solution to the problems of some scenes based on the summary of predecessors. Design pattern is not a formula. There is no need to memorize each pattern by rote. More importantly, it is important to understand its abstract ideas, how to better solve problems by applying design patterns, and what effect can be achieved. Although there are many theories, if we want to master them, many problems will be solved for our practical development.