Design Mode Learning Notebook Handbook

Keywords: Java Database JDK JDBC

Article directory

Classification of GoF Design Patterns

  • Creation type
    Mainly used to create objects
  • Structural type
    It is mainly used to deal with the combination of classes and objects.
  • Behavior type
    Mainly used to describe how classes and objects interact and assign responsibilities

1.1 Creative

  • Abstract Factory
  • Builder Model
  • Factory Method
  • Prototype
  • Singleton

1.2 Structural Type

  • Adapter mode
  • Bridge mode
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

1.3 Behavioral Type

  • Chain of Responsibility
  • Command mode
  • Interpreter pattern
  • Iterator pattern
  • Mediator
  • Memento
  • Observer
  • State
  • Strategy
  • Template Method
  • Visitor mode

II. Overview of Design Principles

2.1 Summary of Object-Oriented Design Principles:

  • Single Responsibility Principle (SRP)
  • Open-Closed Principle (OCP)
  • Liskov Substitution Principle (LSP)
  • Dependency Inversion Principle (DIP)
  • Interface Segregation Principle (ISP)
  • Composite Reuse Principle (CRP)
  • Law of Demeter (LoD)
Design Principle Name Brief Introduction to Design Principles
Principle of Single Responsibility Class responsibilities should be single, not too many responsibilities in one class
Opening and closing principle Software entities are open to expansion, but closed to modification, that is, to expand their functions without modifying a software entity.
Richter's principle of substitution In a software system, a place that can accept base class objects is bound to have a subclass object.
Dependence Inversion Principle Programming for the abstract layer, not for specific classes
Interface Isolation Principle Replacing a unified interface with multiple interfaces
Principle of Composite Reuse Use composition and aggregation Association as much as possible, and use inheritance relation as little as possible.
LoD The fewer references a software entity makes to other entities, the better, or if two classes do not need to communicate directly with each other, then the two classes should not interact directly, but indirectly by introducing a third party.

2.2 Single Responsibility Principle

Single Responsibility Principle Definition: An object should contain only a single responsibility, and that responsibility is fully encapsulated in a class.

The single responsibility principle is the guideline to achieve high cohesion and low coupling.

2.3 Open-Close Principle

Open-Close Principle Definition: A software entity should be open to extensions and closed to modifications. That is to say, when designing a module, it should be extended without modification, that is, to change the behavior of the module without modifying the source code.

In the definition of Open-Close Principle, software entity can refer to a software module, a local structure composed of multiple classes or an independent class.

2.4 Richter Substitution Principle

Riesler's substitution principle is strictly defined: if every object o1 of type S has an object O2 of type T, so that when all program P defined by T replaces all object o1 with o2, the behavior of program P does not change, then type S is a subtype of type T.

A more understandable definition: All references to base classes (parent classes) must be transparent in using objects of their subclasses. It can also be said that in software systems, a place that can accept base class objects can inevitably have a subclass object.

Richter's substitution principle is one of the important ways to realize the open-close principle. Because subclass objects can be used wherever base class objects are used, we try to use base class types to define objects in programs, and then determine their subclass types at runtime, substituting subclass objects for parent class objects.

2.5 Dependence on reversal principle

Definition of Dependence Inversion Principle: High-level modules should not rely on low-level modules, they should all rely on abstraction. Abstraction should not depend on details. Details should depend on abstraction. That is to say, programming for interfaces, not for implementations.

One of the common implementations of the dependency reversal principle is to use abstract classes in code and place concrete classes in configuration files.

2.6 Interface Isolation Principle

Interface isolation principle definition: Once an interface is too large, it needs to be divided into smaller interfaces. Clients using the interface only need to know the relevant methods. That is to say, using multiple interfaces instead of a unified interface

2.7 Principle of Composite Multiplexing

Composition/Aggregate Reuse Principle (CARP) defines the principle of composition/Aggregate Reuse Principle as follows: try to use object composition instead of inheritance to achieve the purpose of reuse. In short: try to use the combination / aggregation relationship, less inheritance.

2.8 Dimiter's Law

The Law of Demeter (LoD), also known as the Least Knowledge Principle (LKP), has many defining methods. Several typical definitions are as follows:

  • (1) Don't talk to strangers. Don't talk to strangers.
  • (2) Communicate only with your direct friends. Talk only to your immediate friends.
  • (3) Each software unit has the least knowledge of other units, and is limited to those software units closely related to the unit. Each unit should have only limited knowledge about other units: only units "close" related to the current unit.

Dimiter's law can be divided into narrow law and broad law. In the narrow sense of Dimiter's Law, if two classes do not need to communicate directly with each other, then the two classes should not interact directly. If one class needs to call a method of another class, the call can be forwarded by a third party.

3. Creative Design Patterns

3.1 Abstract Factory Model

3.1.1 Schema Definition

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their specific classes. The abstract factory pattern, also known as the Kit pattern, belongs to the object creation pattern.

3.1.2 Model Roles

The abstract factory pattern includes the following roles:

AbstractFactory: AbstractFactory

ConcreteFactory: Specific Factory

Product: Specific products

AbstractProduct: Abstract Product

3.1.3 Simple examples

The abstract factory class:

public abstract class AbstractFactory
{
    public abstract AbstractProductA createProductA();
    public abstract AbstractProductB createProductB();
}

Specific factory categories:

public class ConcreteFactory1 extends AbstractFactory
{
    public AbstractProductA createProductA()
    {
        return new ConcreteProductA1();
    }
    public AbstractProductB createProductB()
    {
        return new ConcreteProductB1();
    } 
}

3.1.4 Differences between abstract factory model and factory model

Abstract factory pattern is the most abstract and general form of all forms of factory pattern. The biggest difference between the abstract factory model and the factory method model is that the factory method model aims at a product hierarchy, while the abstract factory model needs to face multiple product hierarchies.

3.2 Builder Model

3.2.1 Schema Definition

Builder pattern belongs to the creation pattern of 23 design patterns, which can be understood as a good way to create objects.

The so-called builder pattern is to ** separate components from component processes, and then build a complex object step by step. ** So the builder mode is also called the generator mode.

3.2.2 Model Structure

The builder model includes the following roles
Builder: Abstract builder
ConcreteBuilder: Specific Builder
Director: Commander
Product: Product role

If the system only needs a specific builder class, the abstract builder can be omitted, and sometimes the commander class can be omitted, so that the builder class acts as both the commander and builder.

3.2.3 Simple examples

Here's a simple example

Product Role Class

public class Product
{
    private String partA;
    private String partB;
    private String partC;
    //... omit set and get methods
}

The Abstract builder class defines the creation and return methods of the product

public abstract class Builder
{
	protected Product product=new Product();
	
	public abstract void buildPartA();
	public abstract void buildPartB();
	public abstract void buildPartC();
	
	public Product getResult()
	{
		return product;
	}

Specific builder class to implement Abstract builder class interface

public class ConcreteBuilder implements Builder {

  Part partA, partB, partC; 
  public void buildPartA() {
    //Here's how to build partA code

  }; 
  public void buildPartB() { 
    //Here's how to build the code for partB
  }; 
   public void buildPartC() { 
    //Here's how to build the code for partB
  }; 
   public Product getResult() { 
    //Return the final assembly result
  }; 

}

Commander class, on the one hand, isolates customers from production process; on the other hand, it is responsible for controlling the production process of products.

public class Director
{
	private Builder builder;
	
	public Director(Builder builder)
	{
		this.builder=builder;
	}
	
	public void setBuilder(Builder builder)
	{
		this.builder=builer;
	}
	
	public Product construct()
	{
		builder.buildPartA();
		builder.buildPartB();
		builder.buildPartC();
		return builder.getResult();
	}
} 

Then the client calls. In the client code, it is not necessary to care about the specific assembly process of the product object, but to determine the type of the specific builder.

Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();

Application of 3.2.4 Model

The most common is String Builder.

JDBC's PreparedStatement class

Ant Manor Chicken Dressed in Ant Gold Clothes can be designed in Builder Mode

Advantages and disadvantages
Advantage:
The client does not need to know the details of the internal composition of the product, and decouples the product itself from the product creation process.

Adding new concrete builders does not need to modify the code of the original class library. The commander class is programmed for the abstract builder class. The system is easy to expand and conforms to the "open-close principle".

Disadvantages:
If the method of building components in-house changes frequently, this situation is not suitable for the builder model.

Although the builder pattern is well decoupled, it may cause too many class objects to be created and load the JVM compared with the singleton pattern. Of course, in appropriate scenarios applications can also improve performance, such as StringBuilder applications.

Comparison of 3.2.5 Models

Through learning, we find that the construction model and the abstract factory model seem to be somewhat similar, so let's compare the two models.

Abstract factory pattern: when the client calls, only the instance factory class is invoked, and then the corresponding method of the factory class is invoked.
Builder mode: When invoked by the client, the generated object can be commanded by the commander, and a complete object can be returned.

3.3 Factory Method Model

3.3.1 Schema Definition

Factory method mode: also known as factory mode, also known as virtual constructor mode, belongs to constructive design mode. Factory method mode is expanded on simple factory mode. The process of producing products is realized by specific factory class, and the base class only implements interfaces. This makes factory method mode can introduce new products without modifying the role of factory.

The mode of working method also conforms to the principle of opening and closing. The factory method pattern is also known as the Virtual Constructor pattern or the Polymorphic Factory pattern.

3.3.2 Model Structure

The factory method pattern consists of the following structures:

Product: abstract product

Concrete Product: Specific Products

Factory: Abstract Factory

ConcreteFactory: Specific Factory

3.3.3 Simple Example

The abstract factory class:

public abstract class PayMethodFactory
{
    public abstract AbstractPay getPayMethod();
}

Specific factory categories:

public class CashPayFactory extends PayMethodFactory
{
    public AbstractPay getPayMethod()
    {
        return new CashPay();
    }
} 


Client call:

PayMethodFactory factory;
AbstractPay payMethod;
factory=new CashPayFactory();
payMethod =factory.getPayMethod();
payMethod.pay(); 

Three factory methods are compared: https://blog.csdn.net/u014427391/article/details/80067882

3.4 Prototype Model

3.4.1 Schema Definition

Prototype Patterns: Prototype Patterns provide a prototype interface, provide prototype cloning, create new objects, is an object creation pattern.

3.4.2 Model Structure

The prototype pattern includes the following roles

  • Prototype: An Abstract prototype class
  • ConcretePrototype: Specific prototype class
  • Client: Customer class

3.4.3 Prototype Patterns Category

A class includes another member variable. If clone method is used directly through super Cloneable interface in object cloning using prototype pattern, this situation does not support cloning of other member variables in the class. This method is called shallow cloning, so the essential difference between shallow cloning and deep cloning is whether it supports member variables in the class. Clone.

In summary, prototype pattern can be used for shallow cloning and deep cloning. The difference is whether it supports the cloning of member variables in a class.

Shallow Cloning of Prototype Patterns
The common implementation of prototype pattern in Java is to rewrite clone() by inheriting the Cloneable interface provided by JDK. This method can also be called shallow cloning of prototype pattern.

public class A implements Cloneable 
{

	
	public Object clone()
	{
		A clone=null;
		try
		{
			clone=(A)super.clone();		
		}
        catch(CloneNotSupportedException e)
        {
        	System.out.println("Clone failure!");
        }
		return clone;
	}
}

Generally speaking, clone method accords with:

  • The same type: for any object a, a.clone().getClass() = a.getClass()
  • Memory address is different: for any object a, a.clone()!=a, the cloned object and the original object are not the same object
  • Equals method for a object: for any object a, a.clone().equals(a)

The example of shallow cloning is from Design Patterns E-mail replication of a Book

Because mail objects contain more contents (such as sender, receiver, title, content, date, attachment, etc.), a system needs to provide a mail replication function. For the created mail objects, a new mail object can be created by replication. If you need to change some contents, you need not modify the original mail object, but only repair it. Change the replicated mail object. The prototype pattern is used to design the system. In this example, shallow cloning is used to achieve mail replication, i. e. replicating email without replicating attachments.

Annex:

public class Attachment
{
    public void download()
    {
    	System.out.println("Download attachments");	
    }
}

Mail class, shallow cloning:

public class Email implements Cloneable 
{
	private Attachment attachment=null;
	
	public Email()
	{
		this.attachment=new Attachment();
	}
	
	public Object clone()
	{
		Email clone=null;
		try
		{
			clone=(Email)super.clone();		
		}
        catch(CloneNotSupportedException e)
        {
        	System.out.println("Clone failure!");
        }
		return clone;
	}
	
	public Attachment getAttachment()
	{
		return this.attachment;
	}
	
	public void display()
	{
		System.out.println("View mail");	
	}
	
}

Client class:

public class Client
{
	public static void main(String a[])
	{
		Email email,copyEmail;
		
		email=new Email();
		
		copyEmail=(Email)email.clone();
		
		System.out.println("email==copyEmail?");
		System.out.println(email==copyEmail);
		
		System.out.println("email.getAttachment==copyEmail.getAttachment?"); 
		System.out.println(email.getAttachment()==copyEmail.getAttachment());			
	}
}

The first one is false and the second one is true. From the previous theory, shallow cloning does not support cloning for member variables, because the address of the object is the same.

Deep Cloning of Prototype Patterns

Above is the realization of shallow cloning. For the realization of deep cloning of prototype pattern, it is usually realized by providing the serialization of classes.

Attachment class, note implements Serializable

import java.io.*;

public class Attachment implements Serializable
{
    public void download()
    {
        System.out.println("Download attachments");
    }
}

The mail class also implements the Serializable interface

import java.io.*;

public class Email implements Serializable
{
	private Attachment attachment=null;

	public Email()
	{
		this.attachment=new Attachment();
	}

	public Object deepClone() throws IOException, ClassNotFoundException, OptionalDataException
	{
		//Write objects into streams
		ByteArrayOutputStream bao=new ByteArrayOutputStream();
		ObjectOutputStream oos=new ObjectOutputStream(bao);
		oos.writeObject(this);

		//Remove objects from the stream
		ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
		ObjectInputStream ois=new ObjectInputStream(bis);
		return(ois.readObject());
	}

	public Attachment getAttachment()
	{
		return this.attachment;
	}

	public void display()
	{
		System.out.println("View mail");
	}

}

Client class:

public class Client
{
	public static void main(String a[])
	{
		Email email,copyEmail=null;

		email=new Email();

		try{
			copyEmail=(Email)email.deepClone();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}


		System.out.println("email==copyEmail?");
		System.out.println(email==copyEmail);

		System.out.println("email.getAttachment==copyEmail.getAttachment?");
		System.out.println(email.getAttachment()==copyEmail.getAttachment());
	}
}

The first one is false and the second one is flase. As can be seen from the previous theory, deep cloning supports cloning for member variables, because the object addresses are the same.

Prototype Manager
Prototype Manager is the Extension of Prototype Patterns
Examples also come from Design Patterns A Book

import java.util.*;

interface MyColor extends Cloneable
{
	public Object clone();
	public void display();
}

class Red implements MyColor
{
   public Object clone()
   {
     Red r=null;
     try
     {
       r=(Red)super.clone();
     }
     catch(CloneNotSupportedException e)
     {  
  
     }
     return r;
   }
   public void display()
   {
     System.out.println("This is Red!");
   }
}

class Blue implements MyColor
{
   public Object clone()
   {
     Blue b=null;
     try
     {
       b=(Blue)super.clone();
     }
     catch(CloneNotSupportedException e)
     {  
  
     }
     return b;
   }
   public void display()
   {
     System.out.println("This is Blue!");
   }
}

class PrototypeManager 
{
   private Hashtable ht=new Hashtable();
   
   public PrototypeManager()
   {
   	  ht.put("red",new Red());
   	  ht.put("blue",new Blue());
   }
   
   public void addColor(String key,MyColor obj)
   {
      ht.put(key,obj);
   }
   
   public MyColor getColor(String key)
   {
      return (MyColor)((MyColor)ht.get(key)).clone();
   }
}

class Client
{
   public static void main(String args[])
   {
      PrototypeManager pm=new PrototypeManager();  
      
      MyColor obj1=(MyColor)pm.getColor("red");
      obj1.display();
      
      MyColor obj2=(MyColor)pm.getColor("red");
      obj2.display();
      
      System.out.println(obj1==obj2);
   }
}

Application of 3.4.4 Model

Scenarios where prototype patterns apply

  • Save the state of the object: For the case that the state to be saved does not occupy memory, the prototype mode and the memo mode can be applied to save the state of the object. If the object occupies too much memory, it is better to use the state mode.

  • Creating new objects is costly: For example, creating an object requires very slow SQL queries to assign values to the object. This situation is suitable for cloning objects in prototype mode, reducing object creation and query.

Scenarios for prototype pattern application

  • For many software replication and pasting implementations are also prototype applications.
  • Spring framework provides BeanUtils.copyProperties method is also the application of prototype pattern

3.5 Singleton Model

3.5.1 Preface

This blog introduces a creative mode: singleton mode
This is a design pattern that is easy to understand and can be understood as a good way to create objects. You can avoid creating too many objects as much as possible, which causes a lot of load to the JVM.

3.5.2 Application Scenario

Some application scenarios of the singleton pattern:
1. For example, data connection classes, which need to be called frequently
2. The service class of website visits statistics needs to be invoked many times.
3. Export and import Excel tables. Some complex systems need to be called many times.
...

To sum up, it is a common class that needs to be invoked frequently. We can design it well with the singleton pattern.
Programming idea
The singleton pattern involves two important programming ideas: lazy loading and caching.

Caching idea:

	private static Singleton instance = null;//Place memory cache first
   
    public static Singleton getInstance() {
        if (instance == null) {//Memory cannot be loaded, create objects
            instance = new Singleton();
        }
        return instance;//Memory cache has, direct call
    }

Lazy Loading Thought:
The following example is a simple application of lazy loading. Create an instance when all the objects are needed, try not to load the class when the instance, this method can avoid adding load to the JVM. This is a good programming habit.

public static Singleton getInstance() {
        if (instance == null) {//Instance only when objects need to be used
            instance = new Singleton();
        }
        return instance;
    }

3.5.3 Example of Singleton Model

Here are some examples of common singleton patterns

1. Lazy Man Model
This is a way that threads are insecure and lazy to load.

public class Singleton {
    private static Singleton instance;
    //Define private constructors so that classes cannot be instanced
    private Singleton (){}

    /**
     * Lazy mode, thread insecurity, lazy loading
     * @return
     */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Threads in the example above are not safe. To ensure thread safety, a synchronization lock can be added, but the performance of the synchronization lock is not good and the load is slow.

public class Singleton {
    private static Singleton instance;
    //Define private constructors so that classes cannot be instanced
    private Singleton (){}

    /**
     * Lazy mode, thread safety, lazy loading
     * @return
     */
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

2. Hungry Han Model
Here's another way to implement the singleton model, the hungry man model.
Its implementation principle is to use the class loading mechanism of Java Virtual Machine to ensure thread safety for a global new object within the class. But obviously, once created, the singleton class is exemplified, which will increase the load of JVM.

public class Singleton {
    //Define private constructors so that classes cannot be instanced
    private Singleton (){}


    //When loading classes, using JVM's class loading mechanism to create objects ensures thread safety, but the efficiency is not good.
    private static Singleton instance = new Singleton();

    /**
     * Hunger mode, thread safety, non-lazy loading
     * @return
     */
    public static Singleton getInstance() {
        return instance;
    }
}

3. Double-checked lock (DCL)
Here's a way to implement double-check locks, which seems a little more complicated, but can achieve thread safety, while double-check locks can ensure high performance.

public class Singleton {
 
    //Define private constructors so that classes cannot be instanced
    private Singleton (){}

    private volatile static Singleton instance;

    /**
     * Double-checked locks (DCL) are thread-safe and lazy to load.
     * @return
     */
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

4. Registered/Internal Classes
Here's how to implement the singleton pattern in the way of inner classes, which can be compared with the hungry man pattern.
This method is similar to the hungry man mode just introduced, but the difference is that it is lazy to load. We can analyze examples. The method is to add an inner class to the singleton class, so that it won't be like the Hungry Man pattern. The singleton class loads the instance object as soon as it is loaded. When the getInstance method is called, the object is created. In this way, lazy loading is achieved, and thread security is guaranteed by using JVM.

public class Singleton {
   
    //Define private constructors so that classes cannot be instanced
    private Singleton (){}

    public static class SingletonHolder{
        private final static Singleton INSTANCE = new Singleton();
    }

    /**
     * Registered/static internal classes, thread-safe, lazy loading
     * @return
     */
    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

5. Enumeration mode
This approach is advocated by Josh Bloch, author of Effective Java. It can not only avoid the problem of multi-threaded synchronization, but also automatically support serialization mechanism, prevent deserialization from re-creating new objects and absolutely prevent multiple instances. However, since the enum feature was added after JDK 1.5, writing in this way can not help feeling strange, and it is seldom used in practical work.

/**
     * Enumeration mode
     */
    public enum Singleton {
        INSTANCE;
        public void whateverMethod() {
        }
    }

4. Structural Design Model

4.1 adapter mode

4.1.1 Schema Definition

Adapter Pattern: Converts an interface to the desired interface of the customer. The adapter pattern enables those classes whose interfaces are incompatible to work together, nicknamed Wrapper. The adapter pattern can be used as either a class-structured pattern or an object-structured pattern.

4.1.2 Model Roles

The adapter pattern includes the following roles

  • Traget (target Abstract class)
  • Adapter (adapter class)
  • Adaptee (adapter class)
  • Client (customer class)

4.1.3 Model Analysis

The adapter pattern decouples the target class from the adapter class and introduces an adapter class to reuse the adapter class. The specific implementation is in the adapter class. Through the adapter pattern, the client class does not know the specific implementation of the adapter class.

Typical class adapter code:

public class Adapter extends Adaptee implements Target
{
	public void request()
	{
		specificRequest();
	}
}

Typical object adapter code:

public class Adapter extends Adaptee implements Target
{
	public void request()
	{
		specificRequest();
	}
}

4.1.4 Model Example

A system needs to provide an encryption module to encrypt user information (such as password and other confidential information) and then store it in the database. The system has defined the database operation class. In order to improve the efficiency of development, it is necessary to reuse existing encryption algorithms, which are encapsulated in some classes provided by third parties, and some even have no source code. Using adapter mode to design the encryption module, the third-party encryption method can be reused without modifying the existing classes.

This example comes from Design Patterns A Book

Target class:

public abstract class DataOperation
{
	private String password;
	
	public void setPassword(String password)
	{
		this.password=password;
	}
		
	public String getPassword()
	{
		return this.password;
	}
	
	public abstract String doEncrypt(int key,String ps);
}

Adapter class:

public final class Caesar 
{
	public String doEncrypt(int key,String ps)
	{   
		String es="";
		for(int i=0;i<ps.length();i++)
		{
			char c=ps.charAt(i);
			if(c>='a'&&c<='z')
			{
				c+=key%26;
			if(c>'z') c-=26;
			if(c<'a') c+=26;
			}
			if(c>='A'&&c<='Z')
			{
				c+=key%26;
			if(c>'Z') c-=26;
			if(c<'A') c+=26;
			}
			es+=c;
		}
		return es;
	}
}

The adapter class:

public class CipherAdapter extends DataOperation
{
	private Caesar cipher;
	
	public CipherAdapter()
	{
		cipher=new Caesar();
	}
	
	public String doEncrypt(int key,String ps)
	{
		return cipher.doEncrypt(key,ps);
	}
}
public class NewCipherAdapter extends DataOperation
{
	private NewCipher cipher;
	
	public NewCipherAdapter()
	{
		cipher=new NewCipher();
	}
	
	public String doEncrypt(int key,String ps)
	{
		return cipher.doEncrypt(key,ps);
	}
}



4.1.5 Model Classification

The adapter mode can be divided into default adapter and bidirectional adapter.

Default adapter
The adapter contains references to both the target class and the adapter class, through which the adapter can invoke methods in the target class and the target class can invoke methods in the adapter class, which is applicable to situations where an interface does not want to use all of its methods. So it is also called single-interface adapter mode.

Two-Way Adapter
If the object adapter contains references to both the target class and the adapter class, the adapter can call methods in the target class through it, and the target class can call methods in the adapter class through it, then the adapter is a bidirectional adapter.

Application of 4.1.6 Model

  • JDBC driver software is an adapter software between JDBC interface and database engine interface. JDBC driver software enables java programs to adapt to various database engines
  • In Spring AOP framework, three notification types, BeforeAdvice, AfterAdvice and ThrowsAdvice, are implemented by adapter mode.

4.2 Bridge Mode

4.2.1 Schema Definition

Bridge pattern is an object structured pattern, which separates the abstract part from the implementation part so that they can be changed independently.

4.2.2 Model Roles

Bridging mode includes the following roles:

  • Abstraction
  • RefinedAbstraction
  • Implementor (Implementing Class Interface)
  • ConcreteImplementor

4.2.3 Model Analysis

The key to bridge mode is how to decouple abstraction and implementation so that they can be changed independently.

Abstraction: Abstraction is to ignore some information and treat different entities as the same entities. The process of extracting the common properties of objects to form classes in object-oriented is called abstraction process.

Realization: The concrete realization of abstract words is realization, and abstraction and realization are reciprocal processes.

Decoupling: Decoupling is to decouple the direct coupling between abstraction and realization, or to change the strong correlation between them into weak correlation, and to change the two roles from inheritance to association (combination or aggregation).

Typical code:

public interface Implementor
{
	public void operationImpl();
} 

public abstract class Abstraction
{
	protected Implementor impl;
	
	public void setImpl(Implementor impl)
	{
		this.impl=impl;
	}
	
	public abstract void operation();
} 

public class RefinedAbstraction extends Abstraction
{
	public void operation()
	{
		//Code
		impl.operationImpl();
		//Code
	}
} 

4.2.4 Model Example

Draw different colors of circles, Draw API interface entity classes Red Circle, Green Circle. Shape is an abstract class with examples from: http://www.runoob.com/design-pattern/bridge-pattern.html

Create a bridge interface:

public interface DrawAPI {
   public void drawCircle(int radius, int x, int y);
}

Interface Specific Implementation Class:

public class RedCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: red, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}
public class GreenCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: green, radius: "
         + radius +", x: " +x+", "+ y +"]");
   }
}

The abstract class association implements the interface:

public abstract class Shape {
   protected DrawAPI drawAPI;
   protected Shape(DrawAPI drawAPI){
      this.drawAPI = drawAPI;
   }
   public abstract void draw();  
}

Specific classes implement Abstract classes:

public class Circle extends Shape {
   private int x, y, radius;
 
   public Circle(int x, int y, int radius, DrawAPI drawAPI) {
      super(drawAPI);
      this.x = x;  
      this.y = y;  
      this.radius = radius;
   }
 
   public void draw() {
      drawAPI.drawCircle(radius,x,y);
   }
}

public class BridgePatternDemo {
   public static void main(String[] args) {
      Shape redCircle = new Circle(100,100, 10, new RedCircle());
      Shape greenCircle = new Circle(100,100, 10, new GreenCircle());
 
      redCircle.draw();
      greenCircle.draw();
   }
}

Print to console:

Drawing Circle[ color: red, radius: 10, x: 100, 100]
Drawing Circle[  color: green, radius: 10, x: 100, 100]

Application of 4.2.5 Model

  • Sometimes bridging mode is also used in cross-platform design of some software.
  • JDBC driver implements the binding of different types of databases to Java programs
  • Java Virtual Machine implements platform independence. Java Virtual Machine design is based on bridge mode.

4.3 Combination Model

4.3.1 Model Intention

Before introducing the definition of schema definitions, we first introduce the intentions of composite schemas. In fact, it is to combine objects into a whole-part hierarchical tree structure. When the client calls, it is the same for calling container objects or composite objects ("branches") and single objects ("leaves").

4.3.2 Schema Definition

Composite pattern: Combining multiple objects to form a tree structure to represent the structural hierarchy of "whole-part".

Composite pattern, also known as "Part-Whole" pattern, belongs to the design pattern of object structure. Objects are grouped into component classes to describe the relationship between whole and part. Composition patterns are consistent with the use of individual objects and composite objects, or container objects.

4.3.3 Model Roles

Combination patterns include the following roles:

  • Component: abstract component
  • Leaf: Leaf Component
  • Composite: Container Component
  • Client: Customer class

4.3.4 Model Analysis

Composition pattern defines an abstract component class, which is mainly used to be called by the client. When the client calls, it does not need to care whether it is a single object or a container object.

Container objects and abstract component classes are aggregated relationships. Container objects can contain either leaves or containers, which can be combined recursively to form a tree structure.

Practical example
Examples come from: Design Patterns A Book

Abstract component classes:

public abstract class Component
{
	public abstract void add(Component c);
	public abstract void remove(Component c);
	public abstract Component getChild(int i);
	public abstract void operation(); 
} 

Leaf type:

public class Leaf extends Component
{
	public void add(Component c)
	{ //Exception handling or error prompt}	
		
	public void remove(Component c)
	{ //Exception handling or error prompt}
	
	public Component getChild(int i)
	{ //Exception handling or error prompt}
	
	public void operation()
	{
		//Implementation code
	} 
} 

Container class:

public class Composite extends Component
{
	private ArrayList list = new ArrayList();
	
	public void add(Component c)
	{
		list.add(c);
	}
	
	public void remove(Component c)
	{
		list.remove(c);
	}
	
	public Component getChild(int i)
	{
		(Component)list.get(i);
	}
	
	public void operation()
	{
		for(Object obj:list)
		{
			((Component)obj).operation();
		}
	} 	
} 

Application of 4.3.5 Model

Application of Combination Mode

  • XML document parsing
  • AWT/Swing of JDK
    ...

4.4 Decoration Mode

4.4.1 Schema Definition

Decoration mode: Decoration mode allows adding new functions to an existing object without changing its structure. Decoration mode is an object structural design mode.

4.4.2 Model Roles

Decoration patterns can be divided into the following roles

  • Component: abstract component
  • ConcreteComponent: Specific Components
  • Decorator: abstract decorative class
  • ConcreteDecorator: Specific Decorator Class

4.4.3 Model Analysis

Interpretation of decorative patterns is easier to understand. There are two ways to add new behavior to a class or object. One is inheritance method, which can make Z subclass have its own method while having its own method. This is a new method of adding class behavior. For another new method of adding class behavior, it is association method, that is, embedding one class into another class. For this class, we call it inheritance method. Decorator

As mentioned above, inheritance mechanism and association mechanism, compared with inheritance mechanism, the advantage of association mechanism is that it does not destroy the encapsulation of classes, and the coupling degree of inheritance is larger than that of association mechanism. So the decoration mode of applying association mechanism is occasionally smaller, which is the advantage of decoration mode, but decoration mode needs to create more objects, which is a disadvantage. Perhaps you can use the hedgehog pattern to reduce class creation.
Following is the classic code for decoration patterns:
Inheritance abstract component interface

public class Decorator extends Component
{
	private Component component;
	public Decorator(Component component)
	{
		this.component=component;
	}
	public void operation()
	{
		component.operation();
	}
} 

Implementing abstract decorative interface with specific decorative types

public class ConcreteDecorator extends Decorator
{
	public ConcreteDecorator(Component component)
	{
		super(component);
	}
	public void operation()
	{
		super.operation();
		addedBehavior();
	}
	public void addedBehavior()
	{
                  //New method	
        }
} 

4.4.4 Model Example

Give Design Patterns An example of multiple encryption in a book:

A system provides a data encryption function, which can encrypt strings. The simplest encryption algorithm is implemented by shifting letters, providing a slightly more complex reverse output encryption, and providing a more advanced modular encryption. Users first use the simplest encryption algorithm to encrypt the string. If they feel that it is not enough to encrypt the results after encryption using other encryption algorithms, of course, they can also encrypt the string for the third time. The multi-encryption system is designed with decorative mode.

Abstract Component Interface:

public interface Cipher
{
	public String encrypt(String plainText);
}

Specific component classes:

public final class SimpleCipher implements Cipher
{
	public String encrypt(String plainText)
	{
		String str="";
		for(int i=0;i<plainText.length();i++)
		{
			char c=plainText.charAt(i);
			if(c>='a'&&c<='z')
			{
				c+=6;
			if(c>'z') c-=26;
			if(c<'a') c+=26;
			}
			if(c>='A'&&c<='Z')
			{
				c+=6;
			if(c>'Z') c-=26;
			if(c<'A') c+=26;
			}
			str+=c;
		}
		return str;
	}
}

The abstract decorative class:

public abstract class CipherDecorator implements Cipher
{
	private Cipher cipher;
	
	public CipherDecorator(Cipher cipher)
	{
		this.cipher=cipher;
	}
	
	public String encrypt(String plainText)
	{
		return cipher.encrypt(plainText);
	}
}

Specific decorative categories:

public class AdvancedCipher extends CipherDecorator
{
	public AdvancedCipher(Cipher cipher)
	{
		super(cipher);
	}
	
	public String encrypt(String plainText)
	{
		String result=super.encrypt(plainText);
		result=mod(result);
		return result;
	}
	
	public String mod(String text)
	{
		String str="";
		for(int i=0;i<text.length();i++)
		{
			String c=String.valueOf(text.charAt(i)%6);
			str+=c;
		}
		return str;
	}
}

public class ComplexCipher extends CipherDecorator
{
	public ComplexCipher(Cipher cipher)
	{
		super(cipher);
	}
	
	public String encrypt(String plainText)
	{
		String result=super.encrypt(plainText);
		result= this.reverse(result);
		return result;
	}
	
	public String reverse(String text)
	{
		String str="";
		for(int i=text.length();i>0;i--)
		{
			str+=text.substring(i-1,i);
		}
		return str;
	}
}

Client class calls:

public class Client
{
	public static void main(String args[])
	{
		String password="sunnyLiu";  //Plaintext
		String cpassword;       //ciphertext
		Cipher sc,ac,cc;
		
		sc=new SimpleCipher();
		cpassword=sc.encrypt(password);
		System.out.println(cpassword);
		
		cc=new ComplexCipher(sc);
		cpassword=cc.encrypt(password);
	    System.out.println(cpassword);
		
		ac=new AdvancedCipher(cc);
		cpassword=ac.encrypt(password);
	    System.out.println(cpassword);
	}
}

Mode application
The most common application of decorative mode is Java IO operation provided by JDK.

  • Abstract component class: InputStream
  • Specific component classes: FileInputStream, ByteArray InputStream, etc.
  • Abstract Decoration Class: FilterInputStream
  • Specific decoration classes: BufferedInputStream, DataInputStream, etc.
    ...

4.4.5 Model Classification

Decoration mode can be divided into transparent decoration mode and translucent decoration mode.

Transparent Decoration Mode
Transparent decoration pattern requires client oriented Abstract programming. Transparency of decoration pattern requires client program not to declare specific component type and specific decoration type, but to declare all of them as abstract component type.

Cipher sc,cc,ac;
sc=new SimpleCipher();
cc=new ComplexCipher(sc);	
ac=new AdvancedCipher(cc);

Translucent Decoration Mode
Semi-transparent decoration mode is quite common. Most decoration modes are semi-transparent decoration mode, rather than transparent, which allows users to declare specific decoration type objects in the client and call new methods in the specific decoration.

Transform camaro;
camaro=new Car();
camaro.move();
Robot bumblebee=new Robot(camaro);
bumblebee.move();
bumblebee.say(); 

4.5 Appearance Model

4.5.1 Schema Definition

Appearance patterns: Appearance patterns provide a unified interface for accessing a group of interfaces of subsystems. Appearance patterns define a high-level interface to make subsystems easier to use. The appearance pattern, also known as the facade pattern, is an object structural design pattern.

4.5.2 Model Roles

As you can see from the pattern definition, the appearance pattern should include the following roles:

  • Frcade: Appearance role
  • SubSystem: Subsystem role
  • Client: Client role

Classic examples:

public class Facade
{
    private SubSystemA obj1 = new SubSystemA();
    private SubSystemB obj2 = new SubSystemB();
    private SubSystemC obj3 = new SubSystemC();
    public void method()
    {
        obj1.method();
        obj2.method();
        obj3.method();
    }
} 

Simple Analysis of 4.5.3 Model

Appearance mode provides convenience for client class. Client class does not need to pay attention to the design of subsystems. It is better to provide access to appearance class directly.

Appearance mode conforms to "Dimiter's Law". A simple interface is introduced to call the client, which reduces the coupling between the client and the subsystem.

However, there are some shortcomings in appearance mode. Each design mode has its shortcomings and advantages. It needs to be selected according to complex business scenarios. If you add an abstract appearance class without reference, you need to adjust the appearance class and client class code once the business changes.

For some very complex business systems, it is sometimes possible to design multiple appearance classes for system decoupling.

4.5.4 Simple Example Practice

An example of JDBC database operation. This example is from Design Patterns A Book

import java.sql.*;

public class JDBCFacade {
    
    private Connection conn=null;
    private Statement statement=null;

    public void open(String driver,String jdbcUrl,String userName,String userPwd) {
        try {
            Class.forName(driver).newInstance();
            conn = DriverManager.getConnection(jdbcUrl,userName,userPwd);
            statement = conn.createStatement();
        } 
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int executeUpdate(String sql) {
        try {
            return statement.executeUpdate(sql);
        } 
        catch (SQLException e) {
            e.printStackTrace();
            return -1;
        }
    }

    public ResultSet executeQuery(String sql) {
        try {
            return statement.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void close() {
        try {
            conn.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Application of 4.5.5 Model

Appearance patterns are suitable for complex systems and can be used for system decoupling. Here's a brief list of some application scenarios for appearance patterns

  • Session in the Java EE framework uses a look-and-feel pattern

  • JDBC database operation that learns JSP also often uses appearance mode.

4.6 hedonic model

4.6.1 Schema Definition

Flyweight Pattern is to reuse a large number of fine-grained objects through sharing technology. The hedonic pattern is shared by fine-grained objects, so it can also be said that the hedonic pattern is a lightweight pattern. According to Gof pattern classification, the hedonic pattern belongs to the object structure pattern.

4.6.2 Model Interpretation

  • Sharable content is called Intrinsic State, and unshareable content that requires external environment settings is called Extrinsic State. The hedonic mode requires the creation of a hedonic factory responsible for maintaining the Flyweight Pool, which is used to store hedonic objects with the same internal state.

  • In the hedonic mode, only the hedonic objects are shared, and the external states need to be set through the environment class. In practice, there are not many internal states that can be shared, so the design of hedonic objects is relatively small, that is, fine-grained objects, so the hedonic mode is to realize the reuse of a large number of fine-grained objects through the sharing technology.

  • Creating a large number of objects will affect the performance of the system to a certain extent. It is not convenient for the program to read, and the use of hedonic mode can reduce the use of objects.

4.6.3 Model Roles

The hedonic model includes the following roles

  • Flyweight: Abstract hedgehog class

  • ConcreteFlyweight: Specific Enjoyment Class

  • UnsharedConcreteFlyweight: Non-Shared Specific Entity Class

  • Flyweight Factory: Heyyuan Factory Class

The core of the hedonic model is the hedonic factory class. The function of the hedonic factory class is to maintain the hedonic pool. What objects are needed from the hedonic pool?

4.6.4 Typical Examples

Examples come from: Design Patterns A Book

public class Flyweight
{
        //Internal state as member attribute
	private String intrinsicState;
	
	public Flyweight(String intrinsicState)
	{
		this.intrinsicState = intrinsicState;
	}
	
	public void operation(String extrinsicState)
	{
		......
	}	
}

public class FlyweightFactory
{
	private HashMap flyweights = new HashMap();
	
	public Flyweight getFlyweight(String key)
	{
		if(flyweights.containsKey(key))
		{
		   //There are objects in Heyuan Pool, which can be obtained directly.
			return (Flyweight)flyweights.get(key);
		}
		else
		{
		    //Create specific hedonic objects and store them in the hedonic pool
			Flyweight fw = new ConcreteFlyweight();
			flyweights.put(key,fw);
			return fw;
		}
	}
} 

Application of 4.6.5 Model

  • The String class in the JDK class library uses the hedonic pattern
    ...

4.6.6 Model Classification

The hedging mode is divided into single-deposit hedging mode and compound hedging mode.

  • Simple Hedonic Model: There is no specific non-shared unit in the simple hedonic model, and all specific hedonic objects can be shared.
  • Compound Hedonic Model: Compound Hedonic Model combines simple Hedonic Model to form Compound Hedonic Object

4.7 Agency Model

4.7.1 Schema Definition

Proxy mode: The proxy mode is to introduce a proxy object to realize the reference of the original object through the proxy object. The proxy pattern is an object structure.

The 4.7.2 proxy pattern includes the following roles

  • Subject: abstract subject roles
  • Proxy: Proxy Theme Roles
  • RealSubject: Real Theme Roles

4.7.3 Model Example

public class Proxy implements Subject
{
    private RealSubject realSubject = new RealSubject();
    public void preRequest()
    {......}
    public void request()
    {
        preRequest();
        realSubject.request();
        postRequest();
    }
    public void postRequest()
    {......}
} 

4.7.4 Mode Types

Come from: Design Patterns A Book of Inductive Classification

  • Remote proxy: Provide a local proxy object for an object located in a different address space, which can be in the same host or in another host. The remote proxy is also called Ambassador.
  • Virtual Agent: If you need to create a resource-consuming object, first create a relatively low-consuming object to represent it. Real objects will be created only when needed.
  • Copy-on-Write proxy: It is a virtual proxy that delays replication (cloning) until the client really needs it. Generally speaking, deep cloning of objects is an expensive operation. Copy-on-Write proxy can delay this operation and only clone objects when they are used.
  • Protect or Access proxy: Controlling access to an object can provide different levels of permission to different users.
  • Cache proxy: Provides temporary storage space for the results of a target operation so that multiple clients can share these results.
  • Firewall Agent: Protect the target from malicious users.
  • Synchronization proxy: enables several users to use an object at the same time without conflict.
  • Smart Reference Agent: When an object is referenced, it provides some additional operations, such as recording the number of times the object is called, etc.

Here's a look at static and dynamic agents

The proxy model is divided into static proxy and dynamic proxy-static proxy: static proxy is to generate proxy classes to complete a series of operations on proxy objects at compilation stage.
Dynamic proxy: Dynamic proxy refers to the generation of proxy classes dynamically at run time. That is, the bytecode of the proxy class will be generated at runtime and loaded into the lassLoader of the current proxy.

4.7.5 Static Agent

Static proxy: Static proxy is the generation of proxy classes at compilation stage to complete a series of operations on proxy objects.
Theme Interface:

public   interface Subject  {    
	abstract   public   void  request(); 
}   

Target objects:

public   class  RealSubject  implements Subject  {    		  	       
   public   void  request()  { 
	   System.out.println( " From real subject. " );     
   }  
}  

Proxy objects:

public   class  StaticProxySubject  implements Subject  { 
    private  RealSubject  realSubject;  // Actual roles as attributes of proxy roles  
    public  ProxySubject()  { }  
    public  void  request()  {  // This method encapsulates the request method of real objects.        
    //Lazy loading, loading only when used
	if ( realSubject  ==   null  )  { 
		realSubject  =   new  RealSubject();        
	}   
	realSubject.request();  // Execute the request method for the real object here   
   } 
}

Write client class:

public class Client{
	StaticProxySubject sps = new StaticProxySubject();
	sps.request();
}

4.7.6 Dynamic Agent

Dynamic proxy: Dynamic proxy refers to the dynamic generation of proxy classes at runtime. That is, the bytecode of the proxy class will be generated at run time and loaded into the lassLoader of the current proxy.
There are many ways to generate dynamic proxy: JDK with dynamic proxy, CGlib, javassist and so on.
JDK Dynamic Agent
Class Proxy. This class is called dynamic proxy class. The most commonly used method of this class is: public static Object new Proxy Instance (Class Loader loader, Class <> [] interfaces, Invocation Handler h) throws Illegal ArgumentException.

The new ProxyInstance () method is used to return an instance of a dynamically created proxy class based on the incoming interface type interface. The first parameter loader in the method represents the class loader of the proxy class, the second parameter interface represents the list of interfaces implemented by the proxy class, and the third parameter h represents the assigned call handler class.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyInvocationHandler implements InvocationHandler {
    private Class<?> target;//Delegate class
    public MyInvocationHandler(Class<?> target){
        this.target=target;
    }
	//Actual execution class bind
    public  Object bind(Class<?> target){
        //Using Proxy provided by JDK to realize dynamic proxy
        return  Proxy.newProxyInstance(target.getClassLoader(),
        		new Class[]{target},this);
    }
    
    @Override
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
		/**Surrounded by agents**/
        //Implementing practical methods
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

CGLIB Dynamic Agent

CGLIB dynamic proxy implements related classes by importing cglib-nodep-2.1_3.jar into the project, which mainly involves two classes:
Method Interceptor interface. It is the interface implemented by the call handler of the proxy instance, which defines the following methods: public Object intercept (Object proxy, Method method, Object [] arg2, Method Proxy mp);

In intercept() method, the first parameter proxy represents the proxy class, the second parameter method represents the method requiring proxy, the third parameter args represents the parameter array of the proxy method, and the fourth parameter mp is used to call the proxy object method.

package com.demo;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MyInterceptor implements MethodInterceptor{	
    private Object target; ;//The target object of the proxy
    public MyInterceptor(Object target) {
        this.target = target;
    } 
//Proxy calls the proxy instance method intercept method args intercept parameters on it
 //invocation is used to call the proxy object method
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, 
                                         MethodProxy invocation) throws Throwable {
        //1. Record logs 2. Time statistics start 3. Safety check
        Object retVal = invocation.invoke(target, args);  
        //4. End of Time Statistics
        return retVal;   
    }
//Method of creating proxy objects
    public Object proxy(Object target) {
		this.target = target;
		Enhancer enhancer = new Enhancer();//This class is used to generate proxy classes		
		enhancer.setSuperclass(this.target.getClass());//Setting parent class
		enhancer.setCallback(this);//Set the callback object as itself
		return enhancer.create();

   }
}

V. Behavioral Design Model

5.1 Responsibility Chain Model

5.1.1 Behavioral Model

Before introducing the responsibility chain pattern, we first introduce the behavioral design pattern, because according to GoF pattern classification, the responsibility chain is a behavioral design pattern. Behavior-based design patterns mainly represent the relationship between classes or objects, which can be divided into category-based design patterns and object-based design patterns. Class behavior is usually realized by inheritance or polymorphism of classes. Object behavior type is realized by association of objects and so on.

5.1.2 Definition of Responsibility Chain Model

Responsibility chain model is an object behavior model. According to the principle of "composite reuse", we try to use association instead of class inheritance. Object behavior pattern can be said to be a good behavior pattern.

The responsibility chain model is a model that separates the sender of the request from the processor of the request. Responsibility chains can be linear, circular or tree-shaped, without the need for details of relationship request processing, as long as the request is sent along the path, so that the requester and the requester are decoupled.

Quote

Chain of Responsibility Pattern: Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

The translation is:

Responsibility chain model: By giving multiple objects the opportunity to process requests, it avoids coupling the sender and receiver of requests. Link the receiving objects together and pass requests along the chain until the object processes it.

5.1.3 Responsibility Chain Model Roles

The responsibility chain model includes the following roles:

  • Handler: Abstract Processor
  • ConcreteHandler: Specific Processor
  • Client: Client

As mentioned above, the sender and the handler of the request are actually the client and the handler of the request are the ConcreteHandler. That is to say, the Client can only send whatever business request it needs. It can completely transform the handler of the ConcreteHandler request without affecting the Client, that is to say, the sender and the handler of the request are accomplished as mentioned above. Decoupling.

5.1.4 Simple Example

For example: Design Patterns A Book

Abstract class:

public abstract class Handler
{
	protected Handler nextHandler;
	
	public void setNextHandler(Handler nextHandler)
	{
		this.nextHandler=nextHandler;
	}
	
	public abstract void handleRequest(String request);
} 

Specific implementers:

public class ConcreteHandler extends Handler
{
	public void handleRequest(String request)
	{
		if(request request Meeting conditions)
		{
			......  //Processing requests;
		}
		else
		{
			this.nextHandler.handleRequest(request); //Forwarding request
		}
	}
} 

Client call:

public class Client
{
	public static void main(String args[])
	{
		Handler handler1 = new ConcreteHandler();
		handler handler2 = new ConcreteHandler();
		handler1.setNextHandler(handler2);
		handler1.handleRequest("test");
	}
}

This example on the Internet is also written, you can refer to learning.
http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

Application of 5.1.5 Model

Exception handling mechanism in Java

try
{
    ...... 			
}catch(IOException e3){
    ......
}finally{
    ......
}

The application of Mybatis Plugin plug-in (interceptor) is also designed and implemented using dynamic proxy and responsibility chain mode:
Take a look at the blog: https://www.jianshu.com/p/b82d0a95b2f3

5.2 Command Mode

5.2.1 Schema Definition

Command pattern: encapsulating a request as an object separates the responsibility of issuing a request from the responsibility of executing a request. The two communicate with each other through the command object, which facilitates the storage, transfer, invocation, addition and management of the command object. Command mode, aliased as Action mode or Transaction mode, belongs to object behavior mode.

5.2.2 Model Roles

Command mode includes the following roles:

  • Client: Customer class, responsible for calling
  • Command: An Abstract command class that declares the interface for executing commands and has an abstract method execute().
  • ConcreteCommand: The concrete command class is the concrete implementation class of the abstract command class. It has the recipient object and completes the operation of the command by calling the recipient's function.
  • Invoker: The caller, the sender of the request, usually has many command objects and executes the related requests by accessing the command objects. It does not directly access the recipient.
  • Receiver: Receiver is the real implementer of the specific command object business.

5.2.3 Model Analysis

The essence of command mode is to encapsulate commands, separating the responsibility of issuing and executing commands.

The actual executor of the command mode is the Receiver. The caller and the receiver communicate through the command object.

Command mode allows the requesting party and the receiving party to separate, so that the requesting party does not need to know the interface of the receiving party, much less how the request is received, whether the operation is executed, when it is executed, and how it is executed.

Typical command mode code

The Abstract command class:

public abstract class Command
{
	public abstract void execute();
} 

Specific command class:

public class ConcreteCommand extends Command
{
	private Receiver receiver;
	public void execute()
	{
		receiver.action();
	}
} 

Caller Invoker class:

public class Invoker
{
	private Command command;
	
	public Invoker(Command command)
	{
		this.command=command;
	}
	
	public void setCommand(Command command)
	{
		this.command=command;
	}
	
	//Business method, a method for call ing command classes
	public void call()
	{
		command.execute();
	}
} 

Receiver class:

public class Receiver
{
	public void action()
	{
		//Specific operation
	}
} 

5.2.4 Typical Examples

Examples come from Design Patterns A Book

The TV is the receiver of the request, and the remote controller is the sender of the request. There are some buttons on the remote controller. Different buttons correspond to different operations of the TV. The Abstract command role is played by a command interface. Three specific command classes implement the abstract command interface. The three specific command classes represent three operations: turning on the TV, turning off the TV and switching channels. Obviously, the TV remote controller is a typical example of command mode application.

The Abstract command class:

public interface AbstractCommand
{
	public void execute();
}

Specific command classes:

Changing platform

public class TVChangeCommand implements AbstractCommand
{
	private Television tv;
	public TVChangeCommand()
	{
		tv = new Television();
	}
	public void execute()
	{
		tv.changeChannel();
	}
}

Shutdown

public class TVCloseCommand implements AbstractCommand
{
	private Television tv;
	public TVCloseCommand()
	{
		tv = new Television();
	}
	public void execute()
	{
		tv.close();
	}
}

Boot up

public class TVOpenCommand implements AbstractCommand
{
	private Television tv;
	public TVOpenCommand()
	{
		tv = new Television();
	}
	public void execute()
	{
		tv.open();
	}
}

Receiver class:

public class Television
{
	public void open()
	{
		System.out.println("Turn on the TV!");
	}
	
	public void close()
	{
		System.out.println("Turn off the TV!");		
	}
	
	public void changeChannel()
	{
		System.out.println("Switch TV channels!");
	}
}

Invoker class

public class Controller
{
	private AbstractCommand openCommand,closeCommand,changeCommand;
	
	public Controller(AbstractCommand openCommand,AbstractCommand closeCommand,AbstractCommand changeCommand)
	{
		this.openCommand=openCommand;
		this.closeCommand=closeCommand;
		this.changeCommand=changeCommand;
	}
	
	public void open()
	{
		openCommand.execute();
	}
	
	public void change()
	{
		changeCommand.execute();
	}	

	public void close()
	{
		 closeCommand.execute();	
	}
}

5.2.5 Applicable Scenarios

  • The system needs to support command Undo and Redo operations.
  • The system needs to combine a set of operations to support macro commands.
  • The system needs to specify, queue and execute requests at different times.
  • The system needs to decouple the caller and the receiver of the request so that the caller and the receiver do not interact directly.

5.3 Interpreter Mode

5.3.1 Schema Definition

Interpreter Pattern: Define the grammar of a language and create an interpreter to interpret sentences in a changed language. The "language" here means code that specifies format and grammar, so the Interpreter pattern is a kind of behavioral pattern.

5.3.2 Model Roles

  • Context: Environment class
  • Client: Customer class
  • AbstractExpression: Abstract Expression
  • TerminalExpression: TerminalExpression
  • NonterminalExpression: Non-terminal expression

5.3.3 Model Analysis

Schema representation, which can be represented by grammar rules or abstract grammar trees

Examples of grammar rules:

  • expression ::= value | symbol
  • symbol ::= expression '+' expression | expression '-' expression
  • Value: = an integer // an integer value

In the definition of grammar rules, some symbols can be used to express different meanings, such as'|'or'{' and'}'for combination, and'*' for 0 or more occurrences, among which the most frequently used symbol is'|'for representation or relationship.

In addition to using grammar rules to define a language, an abstract Syntax Tree (AST) can be used to visually represent the composition of a language in the interpreter pattern. Each abstract grammar tree corresponds to a language instance.

5.3.4 Typical Examples

Typical examples of interpreter patterns:

Abstract expression classes:

public abstract class AbstractExpression
{
	public abstract void interpret(Context ctx);
} 

Terminator expression class:

public class TerminalExpression extends AbstractExpression
{
	public void interpret(Context ctx)
	{
		//Interpretation of Terminator Expressions
	}
} 

Non-terminal expression class:

public class NonterminalExpression extends AbstractExpression
{
	private AbstractExpression left;
	private AbstractExpression right;
	
	public NonterminalExpression(AbstractExpression left,AbstractExpression right)
	{
		this.left=left;
		this.right=right;
	}
	
	public void interpret(Context ctx)
	{
		//Recursively invoke the interpret() method for each component
		//Specify how components are connected in recursive calls, i.e. the function of non-terminators
	}	
} 

Environment class code:

public class Context
{
    private HashMap map = new HashMap();
    public void assign(String key, String value)
    {
        //Setting values to environment classes
    }
public String lookup(String key)    
{
        //Get the values stored in the environment class
    }
} 

Examples come from Design Patterns A Book

5.4 Iterator Mode

5.4.1 Schema Definition

Iterator Pattern: Provides a way to access an aggregated object without exposing its internal representation, nicknamed Cursor, so the iterator pattern is an object behavior type.

5.4.2 Model Roles

  • Iterator: Abstract iterator
  • ConcreteIterator: Specific Iterator
  • Aggregate: An Abstract aggregate class
  • ConcreteAggregate: Specific aggregation classes

5.4.3 Model Analysis

For the iterator pattern, an aggregation can have multiple traversals. In the iterator pattern, an external iterator is provided to access and traverse aggregated objects. The iterator defines an interface to access aggregated objects, which can track traversing elements and know which elements have been traversed and which ones have not.

The iterator pattern applies the factory method pattern, the aggregate class acts as the factory class, and the iterator acts as the product class.

Iterator pattern essence

The essence of iterator pattern: the essence of iterator pattern is to extract the internal data stored in aggregated object, encapsulate it into an iterator, and traverse the internal data of aggregated object through a special iterator.

Main responsibilities of aggregated objects

Aggregated objects have two main responsibilities: one is to store internal data; the other is to traverse internal data; the most basic responsibility is to store internal data.

5.4.4 Typical Examples

Examples come from: Design Patterns A Book

Custom Iterator

Custom Iterator
Client: Client call
MyIterator: An Abstract iterator
MyCollection: An Abstract aggregation class
NewCollection: Specific aggregation classes
NewIterator: Specific Iterator

interface MyCollection
{
	MyIterator createIterator();
}
interface MyIterator
{
	void first();
	void next();
	boolean isLast();
	Object currentItem();
}

class NewCollection implements MyCollection
{
   private Object[] obj={"dog","pig","cat","monkey","pig"};
   public MyIterator createIterator()
   {
  	  return new NewIterator();
   }
   
   private class NewIterator implements MyIterator
   {
   	private int currentIndex=0;
   	
   	public void first()
   	{
   	  	currentIndex=0;
   	}
   	
	public void next()
	{
		if(currentIndex<obj.length)
		{
			currentIndex++;
		}
	}
	
	public void previous()
	{
		if(currentIndex>0)
		{
			currentIndex--;
		}
	}	
	
	public boolean isLast()
	{
		return currentIndex==obj.length;
	}
	
	public boolean isFirst()
	{
		return currentIndex==0;
	}
	
	public Object currentItem()
	{
		return obj[currentIndex];
	}
	
   }
}

class Client
{
	public static void process(MyCollection collection)
	{
		MyIterator i=collection.createIterator();
		
		while(!i.isLast())
		{
			System.out.println(i.currentItem().toString());
			i.next();
		}
	}
	
	public static void main(String a[])
	{
		MyCollection collection=new NewCollection();
		process(collection);
	}
}

5.4.5 Applicable Scenarios

The iterator pattern can be used in the following cases:

  • Accessing the content of an aggregated object without exposing its internal representation.
  • There are many ways to traverse aggregated objects.
  • It provides a unified interface for traversing different aggregation structures.

5.5 Intermediary Model

5.5.1 Schema Definition

Mediator pattern: Mediator pattern encapsulates the interaction of a series of objects with a mediator object, so that there is no need for explicit interaction between objects and the coupling between objects is reduced. Mediator pattern is an object behavior pattern.

So the mediator pattern is applicable to the situation where there are a lot of associations among objects. If an object changes, we need to track its associative objects and make adjustments. The coupling degree is very large, so we can use the mediator pattern to reduce the coupling degree.

5.5.2 Model Roles

The mediator model includes the following roles:

  • Mediator: Abstract mediator
  • Concrete Mediator: Specific Mediator
  • Colleague: An Abstract colleague class
  • Concrete Colleague: Specific colleague class

5.5.3 Model Analysis

Mode effect
The mediator pattern plays a transitional role. When a colleague class needs to be invoked, it is better to invoke the mediator. It does not need to invoke the colleague class. The mediator pattern encapsulates the relationship behavior between colleague objects and plays a coordinating role.

Advantages and disadvantages of patterns
Advantages of the intermediary model:

  • Simplify the interaction between objects
  • Reducing subclass generation
  • Decoupling colleague classes
  • Simplify the design and implementation of colleague classes

Disadvantages of the intermediary model:

  • Because the details of interaction between objects are handled by mediators, the specific mediator class becomes more and more complex with the increase of objects, which makes it difficult to maintain the mediator class.

Schema Classic Code
The Abstract mediator class:

public abstract class Mediator
{
	protected ArrayList colleagues;
	public void register(Colleague colleague)
	{
		colleagues.add(colleague);
	}
	
	public abstract void operation();
}

Specific intermediaries:

public class ConcreteMediator extends Mediator
{
	public void operation()
	{
		......
		((Colleague)(colleagues.get(0))).method1();
		......
	}
} 

Abstract colleague classes:

public abstract class Colleague
{
	protected Mediator mediator;
	
	public Colleague(Mediator mediator)
	{
		this.mediator=mediator;
	}
	
	public abstract void method1();
	
	public abstract void method2();
} 

Specific colleagues:

public class ConcreteColleague extends Colleague
{
	public ConcreteColleague(Mediator mediator)
	{
		super(mediator);
	}
	
	public void method1()
	{
		......
	}
	
	public void method2()
	{
		mediator.operation1();
	}
} 

5.5.4 Typical Examples

Examples come from: Design Patterns A Book

Example: Virtual Chat Room
A forum system would like to add a virtual chat room to allow forum members to exchange information through the chat room. Common Member can send text information to other members. Diamond Member can send text information to other members as well as picture information. The chat room can filter indecent characters and control the size of the pictures sent. The virtual chat room is designed in the mediator mode.

Abstract colleague class
Define a Member class that belongs to the abstract colleague class:

public abstract class Member
{
	protected AbstractChatroom chatroom;
	protected String name;
	
	public Member(String name)
	{
		this.name=name;
	}
	
	public String getName()
	{
		return name;
	}
	
	public void setName(String name)
	{
		this.name=name;
	}
	
	public AbstractChatroom getChatroom()
	{
		return chatroom;
	}
	
    public void setChatroom(AbstractChatroom chatroom)
    {
    	this.chatroom=chatroom;
    }
	
	public abstract void sendText(String to,String message);
	public abstract void sendImage(String to,String image);

    public void receiveText(String from,String message)
    {
    	System.out.println(from + "Send text to" + this.name + ",The contents are:" + message);
    }
    
    public void receiveImage(String from,String image)
    {
    	System.out.println(from + "Send pictures to" + this.name + ",The contents are:" + image);
    }	
}

Specific colleagues
Specific colleague class, inherit Abstract colleague class Member:

Ordinary member

public class CommonMember extends Member
{
	public CommonMember(String name)
	{
		super(name);
	}
	
	public void sendText(String to,String message)
	{
	    System.out.println("Ordinary Members Send Messages:");
	    chatroom.sendText(name,to,message);  //Send out
	}
	
	public void sendImage(String to,String image)
	{
		System.out.println("Ordinary members can not send pictures!");
	}
}

Masonry member

public class DiamondMember extends Member
{
	public DiamondMember(String name)
	{
		super(name);
	}
	
	public void sendText(String to,String message)
	{
	    System.out.println("Diamond Members Send Messages:");
	    chatroom.sendText(name,to,message);  //Send out
	}
	
	public void sendImage(String to,String image)
	{
		System.out.println("Diamond Members Send Pictures:");
	    chatroom.sendImage(name,to,image);  //Send out
	}
}

Abstract mediator class

An Abstract mediator class that defines specific functional methods for chat rooms

public abstract class AbstractChatroom
{
	public abstract void register(Member member);
	public abstract void sendText(String from,String to,String message);
	public abstract void sendImage(String from,String to,String message);
}

Specific intermediary class

Chat room function implementation, do not need to call each other among colleague classes

import java.util.*;

public class ChatGroup extends AbstractChatroom
{
	private Hashtable members=new Hashtable();
	
	public void register(Member member)
	{
		if(!members.contains(member))
		{
			members.put(member.getName(),member);
			member.setChatroom(this);
		}
	}
	
   public void sendText(String from,String to,String message)
   {
   	  Member member=(Member)members.get(to);
   	  String newMessage=message;
   	  newMessage=message.replaceAll("Indecent character","*");
	  member.receiveText(from,newMessage);
   }
   
   public void sendImage(String from,String to,String image)
   {
   	  Member member=(Member)members.get(to);
   	  //Size Judgment of Analog Pictures
   	  if(image.length()>5)
   	  {
   	  	  System.out.println("Picture too big, send failure!");
   	  }
   	  else
   	  {
   	  	  member.receiveImage(from,image);
   	  }
   }
}

Application of 5.5.5 Model

  • Mediator pattern is widely used in event-driven software. Mediator pattern acts as a mediator between components to coordinate component calls.
  • MVC is a basic pattern of Java EE, in which the controller Controller acts as an intermediary responsible for the interaction between View object View and Model object Model.

5.6 Memorandum Model

5.6.1 Schema Definition

Memento Pattern: The definition of a memo pattern is to capture an object's internal state without destroying the encapsulation and save it outside of it so that it can be restored to its original state in the future. So the memo model is an object behavior model.

5.6.2 Model Roles

The memo model includes the following roles

  • Originator
  • Memento (Memorandum)
  • Caretaker

The memorandum model includes the primary device class, the memorandum class and the responsible class. The primary can create a memo, which stores the internal state of the primary, decides which internal state to save according to the primary, and the responsible human is responsible for saving the memo.

5.6.3 Model Analysis

Memorandum mode is mainly used in backup or rollback operations. In order to make software more friendly, there is usually a rollback function. Software generally also needs to provide a rollback mechanism. To achieve rollback, it is necessary to backup the status information in advance. Therefore, with memorandum mode, the system can be rolled back to a specific historical state.

A memo object is a snapshot object that stores the internal state of another object, so a memo mode can be called a Snapshot Pattern or Token mode.

Typical code:

Primary organs:

public class Originator {
  private String state;
  public Originator(){}
  // Create a memo object
  public Memento createMemento(){
    return new Memento(this);
  }
  // Restoring the state of the primary device according to the object of the memorandum
  public void restoreMemento(Memento m){
     state = m.state;
    }
    public void setState(String state)
    {
        this.state=state;
    }
    public String getState()
    {
        return this.state;
    }
}

Memorandum category:

public class Memento {
  private String state;
  public Memento(Originator o){
    state = o.state;
    }
    public void setState(String state)
    {
          this.state=state;
    }
    public String getState()
    {
           return this.state;
     }
} 

Responsible for human:

import java.util.ArrayList;
import java.util.List;
 
public class CareTaker {
   private List<Memento> mementoList = new ArrayList<Memento>();
 
   public void add(Memento state){
      mementoList.add(state);
   }
 
   public Memento get(int index){
      return mementoList.get(index);
   }
}

5.6.4 Model Example

Example: User Information Operation Revocation
A system provides user information operation module, users can modify their own information. In order to make the operation process more humane, the system is improved by using the memo mode, so that users can restore to the state before the operation after the wrong operation.

This example comes from Design Patterns A Book

Primary Class, Create Memorandum Class

package dp.memento;

public class UserInfoDTO
{
	private String account;
	private String password;
	private String telNo;
	
	public String getAccount()
	{
		return account;
	}
	
	public void setAccount(String account)
	{
		this.account=account;
	}

	public String getPassword()
	{
		return password;
	}
	
	public void setPassword(String password)
	{
		this.password=password;
	}
	
	public String getTelNo()
	{
		return telNo;
	}
	
	public void setTelNo(String telNo)
	{
		this.telNo=telNo;
	}
		
	public Memento saveMemento()
	{
		return new Memento(account,password,telNo);
	}
	
	public void restoreMemento(Memento memento)
	{
		this.account=memento.getAccount();
		this.password=memento.getPassword();
		this.telNo=memento.getTelNo();
	}
	
	public void show()
	{
		System.out.println("Account:" + this.account);
		System.out.println("Password:" + this.password);
		System.out.println("TelNo:" + this.telNo);		
	}
}

Memorandum class, save the status of the primary device class:

package dp.memento;

class Memento
{
	private String account;
	private String password;
	private String telNo;
	
	public Memento(String account,String password,String telNo)
    {
    	this.account=account;
    	this.password=password;
    	this.telNo=telNo;
    }
	public String getAccount()
	{
		return account;
	}
	
	public void setAccount(String account)
	{
		this.account=account;
	}

	public String getPassword()
	{
		return password;
	}
	
	public void setPassword(String password)
	{
		this.password=password;
	}
	
	public String getTelNo()
	{
		return telNo;
	}
		
	public void setTelNo(String telNo)
	{
		this.telNo=telNo;
	}
}

Responsible for human, create memo:

package dp.memento;

public class Caretaker
{
	private Memento memento;
	public Memento getMemento()
	{
		return memento;
	}
	public void setMemento(Memento memento)
	{
		this.memento=memento;
	}
}

Application of 5.6.5 Model

  • Archiving in Software
  • ctri + z in Windows.
  • Back operation in IE
  • Transaction management of database
    ...

5.7 Observer Model

5.7.1 Schema Definition

Observer pattern: Observer pattern defines a one-to-many dependency between objects, so that every time an object's state changes, its dependent objects are notified and updated automatically. However, the observer can only know that the target has sent a change, but not how to change it.

5.7.2 Observer Role

The observer pattern includes the following roles:

Subject: Goal

ConcreteSubject: Specific Goals

Observer: Observer

ConcreteObserver: Specific observer

5.7.3 Observer mode "push" and "pull" data

Specific Subject s can notify specific observers to update data in two ways:

(1) push data mode: the specific Subject gives all the changed data to the specific observer;

(2) pull data mode: specific Subject provides the method to obtain data, and specific observer calls the method provided by specific subject to obtain data.

5.7.4 Typical Lists

PS: Code example from Illustrated Design Patterns

Abstract target class

import java.util.*;
public abstract class Subject
{
            protected ArrayList observers = new ArrayList();
	public abstract void attach(Observer observer);
	public abstract void detach(Observer observer);
	public abstract void notify();
} 

Specific target classes

public class ConcreteSubject extends Subject
{
	public void attach(Observer observer)
	{
		observers.add(observer);
	}
	
	public void detach(Observer observer)
	{
		observers.remove(observer);
	}
	
	public void notify()
	{
		for(Object obs:observers)
		{
			((Observer)obs).update();
		}
	}	
} 

Abstract Observer class

public interface Observer
{
	public void update();
} 

Specific Observer class

public class ConcreteObserver implements Observer
{
	public void update()
	{
		//Specific update code
	}
} 

Another good example is the Meteorological Bureau in Head First Design Patterns.

Advantages and disadvantages of 5.7.5 model

Observer advantages: briefly described below, the observer can achieve the separation of the presentation layer and the data logic layer; the observer pattern establishes an abstract coupling between the observer and the observer

Observer Disadvantage: If there is a circular association between the Observer class and the target class, it is easy to cause the system to crash; if there are too many observers, it will take a lot of time to notify all observers.

Application of 5.7.6 Model

Swing, RMI, JDK built-in java.util.Observer interface and java.util.Observable class are all applications of the observer pattern

5.7.7 Classic Meteorological Bureau Example

PS: This column is from Head First Design Patterns.
Look at Head First Design Patterns for yourself. This blog just takes notes for itself.
The following example is from Head First Design Patterns, which is recommended for readers to learn.

Theme Interface, Defining a Theme Interface

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

weatherDate class, in fact, is the implementation class of subject interface. weatherData class implements Subject interface. It is mainly used to register observers, notify observers and so on. When data changes, it notifies registered observers instantly. Code implementation is achieved by cyclic traversal and observers call the updated data interface. Head First Design Patterns provides a built-in class based on JDK. Readers can look at the list of realizations

import java.util.ArrayList;

public class WeatherData implements Subject {
	private ArrayList observers;
	private float temperature;
	private float humidity;
	private float pressure;

	public WeatherData() {
		observers = new ArrayList();//Instance objects, which exist as observer objects through array lists
	}

	public void registerObserver(Observer o) {
		observers.add(o);//Registered observer
	}

	public void removeObserver(Observer o) {
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);//remove observer object
		}
	}

	public void notifyObservers() {//Circular traversal, notifying all registered observers
		for (int i = 0; i < observers.size(); i++) {
			Observer observer = (Observer)observers.get(i);
			observer.update(temperature, humidity, pressure);
		}
	}

	public void measurementsChanged() {
		notifyObservers();
	}

	public void setMeasurements(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}

	// other WeatherData methods here

	public float getTemperature() {
		return temperature;
	}

	public float getHumidity() {
		return humidity;
	}

	public float getPressure() {
		return pressure;
	}
}

Observer interface class

public interface Observer {
	public void update(float temp, float humidity, float pressure);
}

Observer Interface Implementation Class

public interface DisplayElement {
	public void display();
}

public class CurrentConditionsDisplay implements Observer, DisplayElement {
	private float temperature;
	private float humidity;
	public CurrentConditionsDisplay(Subject weatherData) {
		weatherData.registerObserver(this);//Registered observer
	}
	/Update data
	public void update(float temperature, float humidity, float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		display();
	}

	public void display() {
		System.out.println("Current conditions: " + temperature
			+ "F degrees and " + humidity + "% humidity");
	}
}

Print the console

public class WeatherStation {

	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();

		CurrentConditionsDisplay currentDisplay =
			new CurrentConditionsDisplay(weatherData);
		StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
		ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

		weatherData.setMeasurements(80, 65, 30.4f);
		weatherData.setMeasurements(82, 70, 29.2f);
		weatherData.setMeasurements(78, 90, 29.2f);
	}
}

5.8 state mode

5.8.1 Schema Definition

An object changes its behavior when its internal state changes. This object can be called a state object, so the state pattern is an object behavior pattern.

5.8.2 Model Structure

  • Context: Environment class
    Context class can also be called context class, which is actually the object with state and can be understood as state manager.

  • State: abstract state class
    An abstract state class can be either an interface class or an abstract class, but it is implemented through a concrete state class anyway. The abstract state class encapsulates all the action methods in different states of the environment class.

  • ConcreteState: Specific state class
    The concrete implementation class is easy to understand, that is to inherit the abstract state class and implement the concrete method. Not all the abstract methods need to be rewritten. It is better to rewrite according to the change of the state of the environment class. In fact, it is also to change the action method according to the change of the state.

5.8.3 mode applicable scenario

  • State patterns are applicable to business scenarios where behavior changes with state, such as when the state changes, the behavior changes as well.
  • In the case of many conditions in business code, adding some code has a lot of if.. Others, and often change, can be written in state mode.

5.8.4 Business Application Scenario:

  • For example, the approval of OA can apply the state mode. After initiating the application, the approval status may be accepted, approved and so on. Each state has different actions.

  • The role play of the game, each version upgrade of the game will be a change in the state action, using the state mode to design, can improve the extensibility of the program;

5.8.5 Simple Example

Context class:

public class Context {
   private State state;
 
   public Context(){
      state = null;
   }
 
   public void setState(State state){
      this.state = state;     
   }
 
   public State getState(){
      return state;
   }
}

The abstract state class:

public abstract class State {
   public void doAction(Context context);
}

Specific state class:

public class ConcreteState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Start State";
   }
}

Call code:

public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();
 
      ConcreteState concreteState = new ConcreteState();
      concreteState.doAction(context);
 
      System.out.println(context.getState().toString());
 
   }
}

5.8.6 Classification of State Patterns

The state mode can be divided into simple state mode and switchable state mode.

  • Simple state mode
    Simple state mode means that the state is relatively independent, and the concrete state class can be programmed according to the abstract state class, that is, it does not need to change the state with the setState method in the environment class.

  • State mode of switchable state
    The switchable state mode can be changed by the state. When the specific state class is invoked, the setState of the environment class is used to change the state.

5.9 Strategic Model

5.9.1 Schema Definition

Policy pattern: Define a series of algorithms, then encapsulate each algorithm and replace them with each other. That is to encapsulate a series of algorithms into a series of policy classes. Policy pattern is an object behavior pattern. The strategy model conforms to the "open-close principle"“

Strategy Pattern: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

5.9.2 Model Roles

  • Context: Environment class
  • Strategy: An Abstract policy class
  • ConcreteStrategy: Specific Policy Class

5.9.3 Simple Example

Where no strategy pattern is used:

public class Context
{
    ......
    public void method(String type)  
    {
        ......
        if(type == "strategyA")
        {
            //Algorithm A
        }
        else if(type == "strategyB")
        {
            //Algorithm B
        }
        else if(type == "strategyC")
        {
            //Algorithm C
        }
        ......
    }
    ......
} 

The Abstract policy class:

public abstract class AbstractStrategy
{
    public abstract void method();  
} 

Specific strategy categories:

public class ConcreteStrategyA extends AbstractStrategy
{
    public void method()
    {
        //Algorithm A
    }
} 

Environment class:

public class Context
{
    private AbstractStrategy strategy;
    public void setStrategy(AbstractStrategy strategy)
    {
        this.strategy= strategy;
    }
    public void method()
    {
        strategy.method();
    }
} 

Client call:

Context context = new Context();
AbstractStrategy strategy;
strategy = new ConcreteStrategyA();
context.setStrategy(strategy);
context.method();

5.9.4 Policy Mode and State Mode Comparison

Same point:

  • Both strategy mode and state mode belong to behavioral design mode. They are also object behavioral design mode and non-class behavioral design mode.

  • The policy pattern and the state pattern are somewhat similar, and both conform to the closure principle.“

  • Both design patterns can be used to reduce the amount of code if... else

Difference:

  • The specific use of policy mode or state mode can be determined by the state of the environment class. If there are many states, use state mode.

  • When using the policy mode, the environment class needs to select a certain policy class, that is, the client needs to care about the specific state when calling, and call it as needed; while the state mode is not needed, in the state mode, the environment class needs to be placed in a specific state, that is, the algorithm that calls the state class according to the change of the state of the environment class.

I am not familiar with the state mode, so I can refer to a blog I wrote before.
https://blog.csdn.net/u014427391/article/details/85219470

5.10 Template Method Patterns

5.10.1 Schema Definition

The template method pattern defines some skeleton methods in an abstract class, and then defers some methods to the inherited class through the method of class inheritance. Template method pattern is a kind of behavioral pattern, and it is a common method. It does not belong to the object behavioral pattern, because it is only implemented through class inheritance.

Template Method Pattern: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

5.10.2 Model Roles

  • AbstractClass
  • ConcreteClass (Implementation Class)

5.10.3 Model Analysis

Template method, which encapsulates and combines basic methods in an abstract class to form a general algorithm or a method of general behavior.

Components of the template method:

  • Abstract Method
  • Concrete Method
  • Hook Method

Abstract class code:

public abstract class AbstractClass
{
    public void templateMethod()  //Template method
    {
        primitiveOperation1();
        primitiveOperation2();
        primitiveOperation3();
    }
    public void operation1()    //Basic Method - Specific Method
    {
        //Implementation code
    }
    public abstract void operation2();    //Basic method - abstract method
    public void operation3()    //Basic method - hook method
    {
    }
} 

Specific implementation class code:

public abstract class ConcreteClass
{
   /**
    * Basic method - abstract method
    */
    public abstract void operation2(){
        //Concrete realization
    }    
    
    /**
    * Basic method - hook method
    */
    public void operation3(){
        //Concrete realization
    }
} 

Subclasses do not explicitly invoke methods of parent classes, but implement specific business methods through inheritance methods. That is to say, the parent controls the invocation of subclasses. This mechanism is called Hollywood Principle. The Hollywood Principle is defined as "Don't call us, we'll call you".

5.10.4 Specific examples

Examples of database operations. Database operations are divided into connection, opening, using and closing steps. Now we will use mysql, oracle, db2 and other relational databases to write the database operation tool class. For the use of these different databases, in fact, the code of the connection is different, while the code of other operations is similar, so we can use the template method to reuse the code.

ps: This example comes from Design Patterns A book, slightly changed

Template method

public abstract class DBOperator
{   
//Abstract method
	public abstract void connDB();
    public void openDB()
	{
		System.out.println("Open the database");
	}
	public void useDB()
	{
		System.out.println("Using databases");
	}
	public void closeDB()
	{
		System.out.println("close database");	
	}
	//Template method
   public void process()
   {
    connDB();
   	openDB();
   	useDB();
   	closeDB();
   }
}

mysql database

public class DBOperatorMysql extends DBOperator
{
	public void connDB()
	{
		System.out.println("Use JDBC-ODBC Bridging connection Mysql data base");		
	}
}

Oracle database

public class DBOperatorOracle extends DBOperator
{
	public void connDB()
	{
		System.out.println("Use JDBC-ODBC Bridging connection Oracle data base");		
	}
}

call

class Client
{
	public static void main(String a[])
	{
		DBOperator db1;
		
		db1=new DBOperatorMysql();
		db1.process();
		db1=new DBOperatorOracle();
		db1.process();
	}
}

5.10.5 mode application scenario

  • Spring, Struts 2 framework applications, such as framework initialization have applications
    ...

5.11 Visitor Model

5.11.1 Schema Definition

Visitor pattern: Represents an operation on elements in an object structure that enables us to define new operations on elements without changing their classes. So the visitor pattern is an object behavior pattern.

5.11.2 Model Roles

The visitor pattern includes the following roles:

  • Vistor (abstract visitor)
  • ConcreteVisitor
  • Element (abstract element)
  • ConcreteElement
  • Object Structure

5.11.3 Model Analysis

The object structure of the visitor pattern stores different types of element objects for different visitors to access.

Visitor pattern includes two hierarchies, one is Visitor Hierarchy, which provides Abstract visitors and concrete visitors, the other is Element Hierarchy, which provides abstract elements and concrete elements.

The same visitor can access different elements in different ways, and the same element can be accessed by different visitors in different ways.

Typical code:

Abstract visitor class

public abstract class Visitor
{
	public abstract void visit(ConcreteElementA elementA);
	public abstract void visit(ConcreteElementB elementB);
	public void visit(ConcreteElementC elementC)
	{
		//Element ConcreteElementC operation code
	}
} 

Specific Visitor Class

public class ConcreteVisitor extends Visitor
{
	public void visit(ConcreteElementA elementA)
	{
		//Element ConcreteElementA Operational Code
	}
	public void visit(ConcreteElementB elementB)
	{
		//Element ConcreteElementB Operational Code
	}
} 

Abstract element class

public interface Element
{
	public void accept(Visitor visitor);
} 

Specific element classes

public class ConcreteElementA implements Element
{
	public void accept(Visitor visitor)
	{
		visitor.visit(this);
	}
	
	public void operationA()
	{
		//Business method
	}
} 

Object structure class

public class ObjectStructure
{
	private ArrayList list=new ArrayList();
	public void accept(Visitor visitor)
	{
		Iterator i=list.iterator();
		
		while(i.hasNext())
		{
			((Element)i.next()).accept(visitor);	
		}
	}
	public void addElement(Element element)
	{
		list.add(element);
	}
	public void removeElement(Element element)
	{
		list.remove(element);
	}
} 

5.11.4 Model Example

This example comes from Design Patterns A Book

Example 1: Shopping cart
In the supermarket, customers put the selected goods, such as apples, books, etc. in the shopping cart, and then pay at the cashier's office. During the shopping process, customers need to visit these goods in order to confirm the quality of these goods, and then the cashier also needs to visit the goods selected by the customers in the shopping cart when calculating the price. At this time, the shopping cart is used as an Object Structure (object structure) to store various types of goods, and customers and cashiers as visitors to these goods, they need to check and price the goods. Different types of goods may have different forms of access, such as Apple needs to be weighed before pricing, and books do not. Use visitor mode to design the shopping process.

An Abstract visitor class

public abstract class Visitor
{
	protected String name;
	
	public void setName(String name)
	{
		this.name=name;
	}
	
	public abstract void visit(Apple apple);
	
	public abstract void visit(Book book);
}

Specific visitor classes:

public class Saler extends Visitor
{
	public void visit(Apple apple)
	{
		System.out.println("Cashier" + name + "Weigh the apple and calculate its price.");
	}
	
	public void visit(Book book)
	{
		System.out.println("Cashier" + name + "Calculate the price of the book directly.");
	}
}
public class Customer extends Visitor
{
	public void visit(Apple apple)
	{
		System.out.println("customer" + name + "Choose apples.");
	}
	
	public void visit(Book book)
	{
		System.out.println("customer" + name + "Buy books.");
	}
}

Element interface class:

public interface Product
{
	void accept(Visitor visitor);
}

Specific element classes:

public class Apple implements Product
{
  public void accept(Visitor visitor)
  {
      visitor.visit(this);
  }	
}
public class Book implements Product
{
  public void accept(Visitor visitor)
  {
      visitor.visit(this);
  }	
}

Object structure class:

import java.util.*;

public class BuyBasket
{
	private ArrayList list=new ArrayList();
	
	public void accept(Visitor visitor)
	{
		Iterator i=list.iterator();
		
		while(i.hasNext())
		{
			((Product)i.next()).accept(visitor);	
		}
	}
	
	public void addProduct(Product product)
	{
		list.add(product);
	}
	
	public void removeProduct(Product product)
	{
		list.remove(product);
	}
}

Client class:

public class Client
{
	public static void main(String a[])
	{
		Product b1=new Book();
		Product b2=new Book();
		Product a1=new Apple();
		Visitor visitor;
		
        BuyBasket basket=new BuyBasket();
        basket.addProduct(b1);
        basket.addProduct(b2);
        basket.addProduct(a1);
        
        visitor=(Visitor)XMLUtil.getBean();
        
        visitor.setName("Zhang San");
        	
        basket.accept(visitor);
	}
}
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil
{
//This method is used to extract the class name from the XML configuration file and return an instance object.
	public static Object getBean()
	{
		try
		{
			//Creating Document Objects
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
		
			//Get the text node containing the class name
			NodeList nl = doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();
            
            //Generate instance objects by class names and return them
            Class c=Class.forName(cName);
	  	    Object obj=c.newInstance();
            return obj;
           }   
           	catch(Exception e)
           	{
           		e.printStackTrace();
           		return null;
           	}
		}
}

config.xml

<?xml version="1.0"?>
<config>
    <className>Saler</className>
</config>

Application of 5.11.5 Model

  • DOM4j processed by java xml reads and parses XML documents through visitor mode. Visitor Support is the default adapter of Visitor interface provided by DOM4J.
public class MyVisitor extends VisitorSupport 
{
    public void visit(Element element)
    {
        System.out.println(element.getName());
    }
    public void visit(Attribute attr)
    {
        System.out.println(attr.getName());
    }
},

...

Appendix: Reference Course

Posted by phpnewbie911 on Wed, 01 May 2019 22:50:37 -0700