[hard core] 23 kinds of design patterns can help you write beautiful code gracefully!

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(){
    }
}
Thread unsafe:
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;
    }
}
Abstract factory pattern

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();
}
Template method mode

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...");
    }
}
Builder pattern

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;
     }
}
proxy pattern

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);
}
Prototype mode

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;
    }
}
Intermediary model

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();
}
Command mode

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();
    }
}
Responsibility chain model

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);
}
matters needing attention

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");
    }
}
Strategy mode

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);
}
Adapter mode

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();
    }
}
Iterator mode

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;
    }

}
Combination mode

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);
        }
    } 
}
Facade mode

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();
    }
}
Memo mode

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));
    }

}
State mode

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();
}
Interpreter mode

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;
    }
}
Bridge mode

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.

Added by WhiteShade6 on Sat, 05 Mar 2022 03:03:22 +0200