Summary of common design patterns

This article is my study notes, mainly
Learn self fashion Silicon Valley design pattern video Shang Silicon Valley design mode
Factory mode mainly comes from Snail college design mode

1 observer mode

The meteorological station designs an open API to push data to the website. When updating meteorological data, it needs to * * inform (push) * * website at the same time

1.1 general

public class Client {
    public static void main(String[] args) {
        //Create accessor currentConditions
        CurrentConditions currentConditions = new CurrentConditions();
        //Create WeatherData and pass the access party currentConditions to WeatherData
        WeatherData weatherData = new WeatherData(currentConditions);
        
        //Changes in weather conditions
        System.out.println("============Changes in weather conditions=============");
        weatherData.setData(40, 160, 20);
    }
}

This coupling is too strong. When there are many websites that need to be pushed, you have to push them one by one, which is not conducive to maintenance and is not a dynamic website

1.2 observer

Observer mode: a design scheme of many to one dependency between objects. The dependent object is Subject, the dependent object is observer, and the Subject notifies the observer of the change. For example, the weather station here is Subject, which is one of 1. When the user is an observer, it is one of many parties.

Observer interface: observer

//The observer interface implements the observer public interface{


public void update(float temperature, float pressure, float humidity);
}

Interface to be implemented by weather station: subject

public interface Subject {
    public void registerObserver(Observer o); //Registered observer
    public void removeObserver(Observer o); //Remove observer
    public void notifyObserver(); //Notify the observer
}

Weather station itself: it can manage and notify all observers

//Traverse all observers and notify @ Override
public void notifyObservers() {
// TODO Auto-generated method stub for(int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperatrue, this.pressure, this.humidity);
}
}

Main category:

public class Client {
    public static void main(String[] args) {
        //Create weather station WeatherData
        WeatherData weatherData = new WeatherData();

        //Create observer
        CurrentConditions currentConditions = new CurrentConditions();

        //Register with weather data, and you can register many
        weatherData.registerObserver(currentConditions);

        //test
        weatherData.setData(10f,100f,30.3f);
    }
}

1.3 summary

Summary: on the original basis, the core class implements the interface of a manager (subject) and manages multiple observers at the same time. Similar to the original one-to-one wechat notification task between the boss and employees (you need to add private friends and notify them one by one), now the boss directly builds a group and can manage multiple employees at the same time (operate in the group), so that the orders can be issued to each employee in time, and it is convenient to manage the staff

2. Agent mode

2.1 introduction

  • Proxy mode: provide an avatar for an object to control access to the object. That is, the target object is accessed through the proxy object The advantage of this is that on the basis of the realization of the target object, additional function operations can be enhanced, that is, the function of the target object can be extended.

  • The proxied object can be a remote object, an object with high creation cost or an object requiring security control

  • The agent mode has different forms, mainly including three kinds of static agent, dynamic agent (JDK agent, interface agent) and Cglib agent (it can dynamically create objects in memory without implementing interfaces. It belongs to the category of dynamic agent).

2.2 static agent

package com.atguigu.proxy.staticproxy;

//Proxy object, static proxy
public class TeacherDaoProxy implements ITeacherDao{
   private ITeacherDao target; // The target object aggregates the proxied object through the interface

//constructor 
public TeacherDaoProxy(ITeacherDao target) { 
    this.target = target;
}
    
@Override
public void teach() {
   System.out.println("Start agent	Complete some operations..... ");//Additional methods
        target.teach(); //Original method
   System.out.println("Submit.....");//Additional methods
 }
}

Summary: by implementing the same interface, the proxy object can aggregate into the proxy object (@ Autowired). The proxy object can implement additional methods. The disadvantage is that both objects need to implement the same interface, which is troublesome to maintain.

2.3 dynamic agent

package com.atguigu.proxy.dynamic;

public class Client {

public static void main(String[] args) {
// TODO Auto-generated method stub
//Create target object
ITeacherDao target = new TeacherDao();

//Create a proxy object for the target object, which can be converted to ITeacherDao
 
ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

// proxyInstance=class com. sun. proxy.$ Proxy objects are dynamically generated in proxy0 memory
System.out.println("proxyInstance=" + proxyInstance.getClass());

//Call the method of the target object through the proxy object
//proxyInstance.teach();

proxyInstance.sayHello(" tom ");
}

}

import java.lang.reflect.Proxy;


public class ProxyFactory {

//Maintain a target object, Object private Object target;

//Constructor to initialize the target
public ProxyFactory(Object target) {
  this.target = target;
}

//Generate a proxy object for the target object
public Object getProxyInstance() {
//explain
/*
*	public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h)

//1. ClassLoader loader :  Specifies the class loader used by the current target object, and the method to get the loader is fixed
//2. Class<?>[] interfaces:  The interface type implemented by the target object, and use the generic method to confirm the type
//3. InvocationHandler h : In event processing, when the method of the target object is executed, the event processor method will be triggered and the current execution
 The target object method of is passed in as a parameter
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK Agent start~~");
//The reflection mechanism calls the method of the target object 
//The return value of the returnVal method
//args method parameters 
Object returnVal = method.invoke(target, args);
System.out.println("JDK Agent submission"); 
 return returnVal;//Return value of method
}
});
}
}

Three points are summarized...

2.4 Cglib agent

  • The target object needs to implement the interface and use jdk proxy

  • The target object does not need to implement the interface and uses Cglib proxy

MethodInterceptor is in the additional cglib jar package

//MethodInterceptor is in the additional cglib jar package
public class ProxyFactory implements MethodInterceptor {
//Maintain a target object 
    private Object target;

//Constructor, passing in an object to be represented
  public ProxyFactory(Object target) {
	this.target = target;
}

//Return a proxy object: 	 Is a proxy object for the target object
public Object getProxyInstance() {
//1. Create a tool class
Enhancer enhancer = new Enhancer();
//2. Set parent class
enhancer.setSuperclass(target.getClass());
//3. Set callback function
enhancer.setCallback(this);
//4. Create a subclass object, that is, a proxy object
return enhancer.create();


}

//rewrite 	 intercept method, which will call the method of the target object
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("Cglib proxy pattern ~~ start"); 
    Object returnVal = method.invoke(target, args); 
      System.out.println("Cglib proxy pattern ~~ Submit"); return returnVal;
}


}

3. Responsibility chain mode

Purchaser purchases teaching equipment

  1. If the amount is less than or equal to 5000, it shall be approved by the teaching Director (0 < = x < = 5000)

  2. If the amount is less than or equal to 10000, it shall be approved by the president (5000 < x < = 10000)

  3. If the amount is less than or equal to 30000, it shall be approved by the vice president (10000 < x < = 30000)

  4. If the amount exceeds 30000, it shall be approved by the president (30000 < x)

Please design procedures to complete the procurement approval items

3.1 general

Call the handler one by one through the if judgment range

3.2 responsibility chain

3.3 personal summary

When there are multiple if structures, you can consider using the responsibility chain mode, which is a bit similar to linked list traversal, which can improve the decoupling of the program and is easy to add, delete and modify. However, you may need to pay attention to the performance, because traversing too long chain will consume too much performance. The responsibility chain is used in both spring MVC and spring security.

4. Builder mode

  1. Need to build a house: this process is piling, building walls and capping

  2. There are all kinds of houses, such as ordinary houses, high-rise buildings, villas. Although the process of all kinds of houses is the same, the requirements are not the same

  3. Please write a program to complete the requirements

4.1 General

4.2 builder

Emphasize the construction process, rather than getting products in one step. The construction process can be controlled and can be built on demand.

It is used in the source code of stringBuilder

4.3 personal summary

The builder mode emphasizes the process, rather than directly new out like the ordinary mode. The advantage of emphasizing the process is that a step will not be missed, which is similar to cooking. Cooking needs to cut vegetables, fry vegetables and put salt in order, and a step will not be missed by using the builder mode.

At the same time, it separates customers from products. Customers do not need to know the details of products. They can get different products by directly calling different builders

5 factory mode

5.1 simple factory


Advantages: when changing the name of the product on the factory side, it will not affect the client (the server can get the same result by changing the judgment logic)

When it is necessary to expand products, it is troublesome to change the source code of factories and products, which does not comply with the opening and closing principle (expansion and opening)

5.2 factory mode


advantage:

1. It still has the advantage of simple factory: after the server modifies the class name of specific products, the client does not know the details of the lower layer!

2. When the client needs to expand a new product, it does not need to modify the author's original code, but just expand a new factory·

Bar point:

1. We already know that both simple factories and factory methods have an advantage, that is, after the specific product class name on the server side changes, the client does not know!
However, in contrast to our current code, the client still depends on the class name of the specific factory! At this time, if the server modifies the class name of a specific factory, the client should also modify it together! Feel tossed around and back to the origin!

Explanation: the name of the factory is regarded as the interface. The author has the responsibility and obligation to ensure that the name of the factory is stable. In other words, although the client depends on the specific class name of the factory, in the IT industry, the names of all factories tend to be stable (not 100% unchanged). At least the name of the factory class is more stable than the name of the specific product class!

2. Since the product is extended by our own client, why not instantiate it directly? After all, we are the author of the extended Lp product. We can control how we want to change the class name! Why do you have to make factories for your own products?
Explanation: when developing functions, the author will not only develop some abstract products, specific products and corresponding factories, but also match with some frameworks made in advance.

3. The LpFactory is now created so that the LpFactory can be transferred to bussiness Therefore, this LpFactory must be defined Then why not let bussiness from the - beginning Does the taste method directly accept the Food parameter? Instead of the current foodf factory as a parameter.

Explanation: at first, I used the factory because I hoped that when the name of the food was changed, the name of the client would not be changed. Now the parameter is food. Once the name of the product was changed, the name of the client would have to be changed.

Disadvantages:

With more products, the number of product categories and sub factory categories will increase explosively

5.3 Abstract Factory


Abstract factory is suitable for combined products, such as screws and nuts or coke fried chicken. A sub factory can produce two products at the same time to reduce the number of classes.

6 iterator mode

6.1 class diagram


6.2 iterator source code in collection



AbstractList iterator source code

Iterator Itr source code in ArrayList

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    Itr() {}

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();    //Check whether the set has been changed
        int i = cursor;   
        if (i >= size)   //Check length
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;   //The element pointed to by the right pointer (i+1)
        return (E) elementData[lastRet = i];  //Returns the element pointed to by the left pointer (the ith)
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet); //Delete the element pointed to by the left pointer
            cursor = lastRet;  //One digit to the right of the current pointer
            lastRet = -1;  //The left pointer is set to null, so it cannot be remove d continuously
            expectedModCount = modCount;  //Function used to check whether the set has been changed
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

6.3 advantages and disadvantages

advantage:

Implement a sub iterator for each list. When calling the iterator, the upper layer does not need to know the traversal details of the lower layer (regardless of whether it is stored in array or linked list)

The lower layer can realize a variety of data storage forms without affecting the upper layer

7 singleton mode

7.1 hungry Han style

  • static const

    class Singleton{
         private Singleton(){}  //The constructor is privatized. It does not allow external new, but only internal new
         private final static Singleton instance = new Singleton();  //Instantiation is completed when the class is loaded
         public static Singleton getInstance(){  //Provide a public method to obtain an instance
             return instance;
         }
        
    }
    
  • Static code block

    class Singleton{
        private Singleton(){}  //The constructor is privatized. It does not allow external new, but only internal new
        private  static Singleton instance;  
        static{
            instance = new Singleton();// Complete instantiation in static code block
        }
        public static Singleton getInstance(){  //Provide a public method to obtain an instance
            return instance;
        }
    }
    

7.2 lazy style

  • Thread unsafe

    class Singleton{
         private Singleton(){}  //The constructor is privatized. It does not allow external new, but only internal new
         private  static Singleton instance;  
         public static Singleton getInstance(){  //Provide a public method to obtain an instance
             if(instance == null)  //Not created yet. It's the first time
                 instance = new Singleton();
             return instance;  //Already, go back directly
         }
    }
    

    Disadvantages: it is possible for multiple threads to make if judgment at the same time, resulting in confusion

  • Thread safety

    Add a synchronized lock on the thread unsafe method

    public static synchronized Singleton getInstance(){  //Provide a public method to obtain an instance
             if(instance == null)  //Not created yet. It's the first time
                 instance = new Singleton();
             return instance;  //Already, go back directly
         }
    

    Disadvantages: the efficiency is too low. You have to synchronize every time you get an instance

7.3 double check (recommended)

class Singleton{
     private Singleton(){}  //The constructor is privatized. It does not allow external new, but only internal new
     private  static volatile Singleton instance;  //Be careful to add volatile
     public static Singleton getInstance(){ 
         if(instance == null)  {// First inspection
             synchronized(Singleton.class){ //lock up
                  if(instance == null){ //Second inspection
                         instance = new Singleton();
                  }
             }      
         }
         return instance;  //Already, go back directly
     }
}

7.4 static internal class (recommended)

class Singleton{
     private Singleton(){}  //The constructor is privatized. It does not allow external new, but only internal new
     private static class SingletonInstance(){
         private static final Signleton INSTANCE = new Signleton();
     }
     public static Signleton getInstance(){
        return SignletonInstance.INSTANCE;
    }
}

Advantages: it will not be instantiated in advance, and the JVM is thread safe when loading classes

7.5 enumeration (recommended)

Singleton instance = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE; 

enum Singleton{
    INSTANCE;//attribute
     .....
     .....
}

Optimal solution, reason:

  • In the previous method, the private constructor is not safe. You can get a new instance through reflection
  • In the previous method, the two objects before and after serialization are not equal
  • Simple writing

However, there is no delayed instantiation, and there is no guarantee that there is only one instance (you can create one by yourself)

Enumeration is the reason for the optimal solution

8 adapter mode

Working principle: similar to plug incompatibility, add a converter in the middle (universal charging)

  • Class Adapter

  • object adapter

  • Interface adapter

  • Simple MVC adapter

9 strategy mode


All kinds of ducks are equivalent to users

The behavior is equivalent to the provider of the algorithm

Tags: Design Pattern Singleton pattern UML

Posted by n00byboy on Mon, 02 May 2022 23:07:35 +0300