Create a type

The singleton pattern

Singletons can save system resources, and the overhead of creating and dying an object can be minimal. But the daily service interface, even the average small company also has tens of thousands of QPS. Each run of functionality creates new objects to respond to requests, and the creation and destruction of hundreds of thousands of objects is a large overhead, so spring-managed bean objects are typically singletons. Moreover, singleton mode can better solve the problem of concurrency and facilitate the synchronization of data

  • advantages
    • There is only one object in memory, saving memory space
    • Avoid frequent creation and destruction of objects to improve performance
    • Avoid multiple occupation of shared resources and simplify access
    • Provide a global access point for the entire system
  • disadvantages
    • Does not apply to objects that change frequently
/ / the hungry
private static Singleton singleton = new Singleton();
Copy the code
/ / LanHanShi
private static Singleton singleton;
public static Singleton getSingleton(a){
    if (singleton == null) {
        singleton = new Singleton(); // Create passively, only when you really need it
    }
    return singleton;
}
Copy the code
// Double judgment locking mechanism
private volatile static Singleton instance;
// Create a static read-only process helper object while the program is running
public static Singleton GetInstance(a) {
    // Check whether it exists, and then lock
    if (instance == null) {synchronized (Singleton.class){
            if(instance == null){
                instance = newSingleton(); }}}return instance;
}
Copy the code
// Static initialization
private static readonly Singleton instance= new Singleton();
public static Singleton GetInstance(a){
    return instance;
}
Copy the code

The factory pattern

The user does not care about the object instantiation process, only the object acquisition. The factory pattern decouples the product instantiation process from the consumer

  • advantages
    • A caller who wants to create an object simply gets it in the factory by its name or other unique key value
    • High scalability, if you want to increase the production of a type of object, just extend the factory class
  • disadvantages
    • The factory class is not ideal, because for each additional product, a corresponding production judgment logic is added to the factory class, which violates the open and closed principle
public interface Sender{  public void send(a);  }  
public class MailSender implements Sender {  
    @Override  
    public void send(a) {  
        System.out.println("this is mailsender!"); }}public class SmsSender implements Sender {  
    @Override  
    public void send(a) {  
        System.out.println("this is sms sender!"); }}public class SendFactory {  
    public Sender produce(String type) {  
        if ("mail".equals(type)) {  
            return new MailSender();  
        } else if ("sms".equals(type)) {  
            return new SmsSender();  
        } else {  
            return null; }}// If there are other products, add corresponding produce method in the factory
}  
Copy the code

Builder model

It mainly solves the creation of a complex object in the software system, which is usually composed of sub-objects of each part with a certain algorithm. The pieces of this complex object often face drastic changes due to changing requirements, but the algorithms that put them together are relatively stable

  • advantages
    • Good expansibility, each attribute of the object is constructed independently of each other, which is conducive to decoupling.
    • The builder can gradually refine the creation process without any impact on other modules, making it easy to control the risk of detail
  • disadvantages
    • If the object builder changes, the builder also changes, resulting in high maintenance costs
    • One builder for each type of builder, it is almost impossible for a builder to build multiple types of objects
@Data
class Product {
    private String name;
    private String price;
    // The Builder of Product
    public static class Builder{
        public static Builder builder(a){
            Builder builder = Builder();
        }
        private Product product = new Product();
        public Builder name(String name){ product.name = name; return this; }public Builder price(String price){ product.price = price; return this; }
        // Return the product object
        public Product build(a) { returnproduct; }}}Copy the code

structured

Adapter mode

Connect upstream and downstream functions. Generally, the existing functions are incompatible with the interface required by the product, and conversion adaptation is required. The conversion between PO, BO, VO and DTO model objects is also a process of adaptation

  • Advantages: improved class reuse, good flexibility
  • Disadvantages: Too much use of adapters, will make the system very messy, not easy to grasp the whole. For example, it is obvious that interface A is called, but in fact it is internally adapted to the implementation of interface B
// The adapter schema for the class
public class Source {  
    public void sayHello(a) {  
        System.out.println("lwl:hello!"); }}public interface Targetable {  
    /* Source the same method */  
    public void sayHello(a);  
    /* New method */  
    public void hi(a);  
}
// Source ADAPTS to Targetable with Adapter
public class Adapter extends Source implements Targetable {  
    @Override  
    public void hi(a) {  
        System.out.println("csc:hi!"); }}Copy the code
// The adapter mode of the object
public class Source {  
    public void sayHello(a) {  
        System.out.println("lwl:hello!"); }}public interface Targetable {  
    /* Source the same method */  
    public void sayHello(a);  
    /* New method */  
    public void hi(a);  
}
// The Source object is adapted to Targetable
public class Adapter implements Targetable {
    private Source source;  
    public Adapter(Source source){ this.source = source; }
    public void sayHello(a){ source.sayHello(); }
    @Override  
    public void hi(a) {  
        System.out.println("csc:hi!"); }}Copy the code

Decorator mode

Enhance object functionality. Dynamically add functionality to an object, and also dynamically undo it. (Inheritance does not do this. Inheritance functions are static and cannot be added or deleted dynamically.)

public interface Show(a){ public void acting(a); }
public class Artist implements Show {  
    public void acting(a){
        System.out.println("LWL is singing!"); }}public class DecoratorArtist implements Show{
    Artist artist;
    DecoratorArt(Artist artist){
        this.artist = artist;
    }
    public void acting(a){
        System.out.println("LWL is playing the piano!"); // Enhanced functionality
        this.artist.acting(); 
        System.out.println("Show over!); // Enhanced functionality}}Copy the code

The proxy pattern

The proxy class is the intermediary between the client class and the delegate class. You can extend the function of the delegate class by adding additional functions to the proxy class, so that only the proxy class needs to be modified without modifying the delegate class, in accordance with the open and closed principle of code design

  • The difference from decorator mode: The proxy mode focuses on enhancing the functionality of the class and masks the creation process of the original object. The decorator pattern enhances objects, and the decorator pattern has a step that dynamically passes the original object
  • The advantages of the adapter pattern are similar to those of objects: whereas the proxy pattern focuses on enhancements to the original functionality, the adapter pattern focuses on compatibility with the new functionality
  • Advantages -1. Clear responsibilities. 2. High scalability
public class Artist implements Show {  
    public void acting(a){
        System.out.println("LWL is singing!"); }}public class ProxyArtist implements Show{
    Artist artist;
    ProxyArtist(){ 
        this.artist = new Artist();// Mask the creation of the Artist object
    }
    public void acting(a){
        System.out.println("LWL is playing the piano!"); // Enhanced functionality
        this.artist.acting(); 
        System.out.println("Show over!); // Enhanced functionality}}public class Demo {
    public static void main(String[] arg){
        Show show = newProxyArtist(); show.acting(); }}Copy the code

The bridge model

The bridge pattern focuses on the abstraction of functionality to build upper-level functionality based on these abstract interfaces. Common Java projects separate the interface from the implementation, based on the bridge pattern. Improve the system’s ability to expand, when the underlying logic of the reference has different design implementation, inherit the abstract interface to achieve a set of can, the old unchanged, in line with the open and closed principle of code design

  • JDBC driver: common JDBC and DriverManager, JDBC to connect to the database, switch between the various databases, basically do not need to move too much code, the reason is that JDBC provides a unified interface, each database to provide their own implementation, with a called database driver program to bridge
  • Unix File systems: The VIRTUAL File System (VFS) enables Unix systems to read and write data from different File systems on different physical media
public interface FileSystem(a){ 
  public void open(int file); 
  public String loading(int file); 
  public void store(int file, String data); 
}
// The file system on the network
public class NetFileSystem implements FileSystem {  
  public void open(int file){ System.out.println(" netfile opening...."); }
  public String loading(int file) {System.out.println(" net loading ...."); }  
  public void store(int file, String data) {System.out.println(" send to network ...."); }}// Disk file system
public class DiskFileSystem implements FileSystem{
  public void open(int file){ System.out.println(" disk opening...."); }
  public String loading(int file) {System.out.println(" disk loading ...."); } 
  public void store(int file, String data) {System.out.println(" write back disk ...."); }}public class Linux {
    FileSystem fileSystem; 
    // The underlying function provides interface, bridge mode: function and concrete implementation are separated
    // You can bridge NetFileSystem or DiskFileSystem as a file system
    public void set(FileSystem fileSystem){ this.fileSystem = fileSystem; }
    // The upper-layer function reads data
    public String read(int file){ fileSystem.open(file); .// Linux's own system functionsfileSystem.loading(file); . }// Write data
    public String write(int file, String data){ fileSystem.open(file); . fileSystem.store(file,data); }}Copy the code
  • Can be used in conjunction with adapter mode

The flyweight pattern

Multiple objects share certain properties. When creating a large number of objects, it is possible to run out of memory and abstract out the common parts. If there is the same request, return the same attribute in memory to avoid re-creation

  • For example, connection objects in JDBC connection pools share attributes such as URL, driverClassName, username, and Password of the pool object
public class ConnectionPool {  
    private Vector<Connection> pool;  
    /* Public attributes */  
    private String url = "jdbc:mysql://localhost:3306/test";  
    private String username = "root";  
    private String password = "root";  
    private String driverClassName = "com.mysql.jdbc.Driver";  
    public ConnectionPool(a) {  
        pool = new Vector<Connection>(poolSize);  
        for (int i = 0; i < poolSize; i++) {  
            Class.forName(driverClassName);  
                // Each CONN shares driverClassName, URL, username, password, etcConnection conn = DriverManager.getConnection(url, username, password); pool.add(conn); }}... }Copy the code

The appearance model

  • Implement a more complex set of functions with multiple different objects. Decouple the relationships between classes. For example, Spring implements complex services using simple components and DAOs
  • Combination of functions. Composition is better than inheritance
public class DAO { 
    public void queryData(a){
        System.out.print(" query data ")}}public class Deal {  
    public void dealData(a){
        System.out.print(" dealing data ")}}public class Sender {  
    public void send(a){
        System.out.print(" send data ")}}public class Service(a){
    private DAO dao;  
    private Deal deal;  
    private Sender sender;
    // Encapsulate DAO, Deal, Sender functions, unified external services
    public void reponse(a){ dao.queryData(); deal.dealData(); sender.send(); }}Copy the code

Behavior type

The strategy pattern

The policy pattern focuses on different scenarios using different policies. In the case of multiple similar algorithms, solve if… Else is complex and difficult to maintain

  • The difference between bridge mode and bridge mode: Bridge mode is a structural mode, focusing on the separation of the abstraction and implementation of the underlying function, even if there is only one implementation of the underlying function
// School strategy
abstract class Strategy{
    private static final Map<Integer,Strategy> strategyMap = new ConcurrentHashMap<>();
    public Strategy(a){
        strategyMap.put(getType(), this);
    }
    public static Strategy routing(int type){
        return strategyMap.get(type);
    }
    abstract int getType(a);
    abstract void method(a); // Leave it to subclasses to implement the difference
}
// Run to school
class RunningStrategy extends Strategy{
    int getType(a) { return 0; }
    void method(a) { System.out.println(" Run to school "); }}// Go to school by bus
class BusStrategy extends Strategy{
    int getType(a) { return 1; }
    void method(a) { System.out.println(" Go to school by bus "); }}// Fly to school
class FlyStrategy extends Strategy{
    int getType(a) { return 2; }
    void method(a) { System.out.println(" Fly to school "); }}class Context{
    // Use different strategies
    void method(int strategy){ Strategy.routing(strategy).method(); }}Copy the code

Template method

It is similar to the shared element mode. The shared element mode focuses on the sharing of attributes, and it is a reference on the structure, and does not necessarily need inheritance. While template methods share the same behavior, there must be inheritance behavior

  • It differs from the policy pattern in that it has a common behavior that can be abstracted out, and each subclass implements different details
abstract class AbstractHandler{
    // Handle is abstract common logic
    void handle(String data){
        System.out.println("General logic 1...");
        stepOne(data);
        System.out.println("General Logic 2...");
        stepTwo(data);
        System.out.println("General Logic 3...");
    }
    abstract void stepOne(String data); // Leave it to subclasses to implement the difference
    abstract void stepTwo(String data); // Leave it to subclasses to implement the difference
}
class HelloHandler extends AbstractHandler{
    @Override
    void stepOne(String data) {
        System.out.println("hello: "+data);
    }
    @Override
    void stepTwo(String data) {
        System.out.println("hi: "+data); }}Copy the code

Iterative subpattern

Loop through multiple identical objects, used to traverse collections or arrays

// The iterated abstract interface
public interface Iterator {  
    / / forward
    public Object previous(a);  
    / / move backward
    public Object next(a);  
    public boolean hasNext(a);   
} 
// Array iterator class
public class ArrayIterator implements Iterator {  
    private Object[] datas; 
    private int cur = 0;  
    public ArrayIterator(Object[] datas){  
        this.datas = datas;  
    }  
    public String previous(a) {  
        if(cur > 0){ cur--; }return datas[cur];  
    }  
    public Object next(a) {  
        if(cur < datas.length-1){ cur++; }return datas[cur];  
    }  
    public boolean hasNext(a) {  
        return pos < datas.length-1 ? truefalse; }}Copy the code

Chain of Responsibility model

Responsible for processing objects passed upstream and passing them on to the next handler

  • Different from the iterative sub-mode, the responsibility chain mode is that multiple Handers process the same data, and the hander processing is sequential. Instead of all handers processing, it can be interrupted in a certain hander or continued transmission
abstract class Handler<T.R> {
    privateHandler<R,? > next;abstract R handle(T data);
    public void setNext(Handler
       
         next)
       ,>{ this.next = next; }
    public void loopHandle(T data){
        R result = this.handle(data);
        if(next! =null&& result! =null) { next.loopHandle(result); }}}// Do the greeting
class HelloHandler extends Handler<String.Integer> {
    Integer handle(String data) {
        System.out.println(data + " hello! ");
        return 10; }}// Take charge of counting
class CountHandler extends Handler<Integer.Double> {
    Double handle(Integer data) {
        System.out.println(" it is " + data);
        return 2.0; }}public class demo{
    public static void main(String[] args){
        HelloHandler hello = new HelloHandler();
        CountHandler count = new CountHandler();
        hello.setNext(count);
        hello.loopHandle("lwl"); }}Copy the code

Observer model

Event notification: Defines a one-to-many dependency between objects in which all dependent objects are notified when an object’s state changes

  • Advantages: Observer and observed are abstractly coupled
  • disadvantages
    • If an observed object has many direct and indirect observers, it can take a long time to notify all of them
    • If there is a cyclic dependency between the observer and the observing target, the observing target will trigger a cyclic call between them, possibly causing the system to crash
/ / observer
public abstract class Observer<T> {
    public abstract void update(T data);
}
// The observed object
public class Subject<T> {
    private List<Observer<T>> observers = new ArrayList<>();
    private T state;
    public void deal(a) {...// Logical processing
        // Notify the observer if state is changed
        if(...). notifyAllObservers(); }// Add an observation observation
    public void observe(Observer<T> observer) {
        observers.add(observer);
    }
    public void notifyAllObservers(a) {
        for(Observer<T> observer : observers) { observer.update(state); }}}Copy the code

State machine mode

Different states of different responses to achieve the transfer between states

  • And the strategic pattern
    • The state machine pattern is the twin of the policy pattern. In the policy mode, users can specify the new policy algorithm. In the state machine mode, the status is automatically changed when certain conditions are met. Users cannot specify the status and can only set the initial status
    • The state machine mode focuses on switching between states to do different things; The policy mode focuses on selecting policies based on specific situations and does not involve switching
interface State<T> {
    // The current state processes the data and returns the next state
    abstract State<T> action(T data);
}
@Data
class Context<T>{
    private State<T> state;
    public void invoke(T data){ state ! =null ? state = state.action(data) : System.out.println(" nothing "+ data); }}// HelloState -> HiState
class HelloState implements State<String>{
    public State<String> action(String data) {
        System.out.println("hello!" + data);
        return newHiState(); }}// HiState -> FineState
class HiState implements State<String>{
    public State<String> action(String data) {
        System.out.println("how are you ?" + data);
        return newFineState(); }}// The final state
class FineState implements State<String>{
    public State<String> action(String data) {
        System.out.println("I am fine!");
        return null; }}public class demo{
    public static void main(String[] args){
        Context<String> context = new Context<>();
        context.setState(new HelloState());
        context.invoke("lwl");
        context.invoke("lwl");
        context.invoke("lwl");
        context.invoke("lwl"); }}Copy the code

The memo

Records the last status for easy rollback. Most of the time we need to record the current state, the purpose of this is to allow the user to cancel the uncertain or incorrect operation and restore the original state

  • Disadvantages: Consumption of resources. If a class has too many member variables, it will take up a lot of resources, and each save will consume a certain amount of memory
@Data
public class Memento { 
    private String state;
    public Memento(String state){ this.state = state; }}@Data
public class Storage { 
    private String value;  
    public void storeMemento(a){
        return new Memento(value);  
    }
    public void restoreMemento(Memento memento){  
        this.value = memento.getValue();  
    }
    public void action(a){ System.out.println("Storage class logical run");}
      
}
public class MementoPatternDemo { 
    public static void main(String[] args) {
        Storage storage = new Storage();
        storage.setValue(1);
        storage.storeMemento();// A reminder
        storage.action();/ /... The logical operation
        restoreMemento(Memento memento);// Use the restore state of the memo}}Copy the code