Design patterns in Java (three are introduced here)

1, What is a design pattern

Design pattern is the solution to the general problems faced by software developers in the process of software development. These solutions are summarized by many software developers after a long period of experiments and errors.
Design pattern is a set of code design experience that is used repeatedly, known by most people, classified and catalogued

2, The role of design patterns

The purpose of using design module is to reuse the code, make the code easier to be understood by others and ensure the reliability of the code

3, Common design patterns

  There are 23 common design models
3.1 singleton mode
Single class mode -- ensure that there is only one instance of a class
When classes are frequently created and destroyed, we use singleton mode, which can reduce the memory overhead and avoid multiple occupation of resources
Singleton mode conditions:
1. Construction method
2. Provide a static method [public] to return the created current class object
Two representations:
1. Lazy style
For example:

package com.wangxing.test1;
/*
 * Lazy style
 */
public class lanhan {
	//Create construction method
	public lanhan(){}
	//First create the lanhan object
	private static lanhan obj=null;
	//The method of creating excessive lanhan class objects can avoid creating new objects every time and reduce the memory overhead
	public static lanhan getlanhanClass(){
		if (obj==null) {
			obj=new lanhan();
		}
		return obj;
	}
}


2. Hungry Han style
For example:

package com.wangxing.test1;
/*
 * Hungry Han style
 */
public class ehan {
	//Create construction method
	public ehan(){}
	//Create ehan objects in advance
	private static ehan obj=new ehan();
	//Create a method to get the object
	public synchronized static ehan getehanClass(){
		return obj;
	}
}

The difference between lazy and hungry
Same point: ensure that there is only one object of the current class
On writing:
         1. Construction method
          2. Provide a static method [public] to return the created current class object
difference:
         Writing: the object variable of the current class saved in the lazy style is initially null,
                    Save the object variable of the current class in the new expression, and the current class object with the initial value of new
         Running speed: the lazy type is slightly worse than the hungry type.
         Resource utilization: the hungry type is slightly worse than the lazy type.
3.2 factory mode
Factory pattern - there is a special Java class that acts as a factory for production objects
Conditions for using factory mode:
1. Large demand
2. Pull one hair and move the whole body
Roles in factory mode:
        Factory role - production object
        Abstract product object - [ abstract / interface ]
        Specific products ------ [abstract class / interface class]
For example, there are all kinds of fruits on the farm and watermelon. Apples, bananas, etc
            Factory role - agricultural factory
             Abstract product role ---- fruit
            Watermelon, apple, banana - specific products
1. First create the common function interface of the abstract product

package com.wangxing.test2;

public interface ShuiGuo {
	void eat();
}

2. Create the class inheritance function of each specific fruit

package com.wangxing.test2;

public class PingGuo implements ShuiGuo{

	@Override
	public void eat() {
		System.out.println("I'm an apple. I need to wash it and eat it later!!!");
	}
}
package com.wangxing.test2;

public  class xigua implements shuiguo{

	@Override
	public void eat() {
		System.out.println("I'm watermelon, cut and eat");
	}
}

3. The user who creates the farm selects the fruit as the system menu, and obtains the reflection object corresponding to a fruit according to the menu to create an instance object
menu.txt
Apple = com.wangxing.test2.pingguo
Watermelon = com.wangxing.test2.xigua
4. Create an agricultural factory to realize the factory mode

package com.wangxing.test2;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;

/**
 * 
 * @author Administrator
 *
 */
public class NongChang {

	public  static  ShuiGuo  createShuiGuo(String name){
		ShuiGuo  sg=null;
		//Read menu
		HashMap<String,String>  menuMap=readMenu();
		String className=menuMap.get(name);
		try{
		//Create objects using reflection mechanism
	    Class  classobj=Class.forName(className);
	    sg=(ShuiGuo)classobj.newInstance();
		}catch(Exception e){
			e.printStackTrace();
		}
		return sg;
	}
	/**
	 * Read menu	
	 */
	private static HashMap<String,String> readMenu() {
		HashMap<String,String>  menuMap=new HashMap<String,String>();
		try{
		BufferedReader  read=new BufferedReader(new FileReader(new File("menu.txt")));
		String menuitem=null;
		while((menuitem=read.readLine())!=null){
			//Apple = com.wangxing.test2.PingGuo
			String menuarray[]=menuitem.split("=");
			menuMap.put(menuarray[0],menuarray[1]);
		}
		read.close();
		}catch(Exception e){
			
		}
		return menuMap;
	}
}

5. Create test class

package com.wangxing.test2;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TestMain {

	public static void main(String[] args) throws Exception{
		BufferedReader  read=new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Please enter the desired fruit:");
		String  name=read.readLine();
		ShuiGuo   pg=NongChang.createShuiGuo(name);
		pg.eat();
	}

}

  At this time, we do not need to judge the user's needs and then go to the new fruit object every time, but leave it to the factory to create an instance object to get specific things. Avoid repeated code writing.
3.3 agent mode
Proxy mode - provides a proxy for other objects to control access to this object
Buying train tickets is not necessarily at the railway station, but also at the consignment point
Agent mode is divided into static agent and dynamic agent
Static agents are divided into brother mode and parent-child mode
Disadvantages: additional business functions need to be provided to implement similar subclasses [heavy workload]
Brother mode -- two subclasses of the same interface
For example:
1. Create an interface with common functions between the railway station and the consignment point

package com.wangxing.test3;

public interface SellPiao {
	void maiPiao();
}

2. Let the railway station and the consignment point inherit this interface

package com.wangxing.test3;

public class huoCheZhan implements SellPiao{

	@Override
	public void maiPiao() {
		System.out.println("I'm a train ticket. I bought a ticket at the railway station");
	}
}
package com.wangxing.test3;

public class daiShouDian implements SellPiao{

	@Override
	public void maiPiao() {
		System.out.println("I'm a sales agent. I'm buying tickets");
	}
}

3. Test

package com.wangxing.test3;

public class Main {

	public static void main(String[] args) {
		huoCheZhan hcz=new huoCheZhan();
		hcz.maiPiao();
		daiShouDian dsd=new daiShouDian();
		dsd.maiPiao();
	}
}

  Parent child mode --- inheritance relationship
1. Create a parent class

package com.wangxing.test4;

public class huoCheZhan {
	public void maipiao(){
		System.out.println("This is the railway station. I'm selling tickets");
	}
}

2. Create a subclass to inherit the parent class and override the ticket selling method

package com.wangxing.test4;

public class daiShouDian extends huoCheZhan{
	public void maipiao(){
		System.out.println("I'm an agent. I'm selling tickets");
	}
}

3. Test

package com.wangxing.test4;

public class Main {
	public static void main(String[] args) {
		huoCheZhan hc=new huoCheZhan();
		hc.maipiao();
		daiShouDian ds=new daiShouDian();
		ds.maipiao();
	}
}

Dynamic proxy - a java class is responsible for creating the object of the proxy class
     JDK dynamic proxy -- create proxy class objects through the java.lang.reflect package Class Proxy class
    [proxy class objects can only be provided for java classes that have implemented an interface]
For example:
1. Create interface

package com.wangxing.test5;

public interface SellPiao {
	void maipiao();
}

2. Create a class that inherits the interface

package com.wangxing.test5;

public class huoCheZhan implements SellPiao{

	@Override
	public void maipiao(){
		System.out.println("This is the railway station. I'm selling tickets");
	}
}

3. Create a dynamic proxy, get the reflection object through the class implementing the interface, so as to get the method of interface subclass inheriting the interface, and directly create a new object, but the method of interface subclass is still used

package com.wangxing.test5;

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

public class ProxyObject implements InvocationHandler{
	  //Define target object
	  private  Object targetObject;
	  
	  public ProxyObject(Object targetObject){
		  this.targetObject=targetObject;
	  }
	  
	  //Get proxy object
	  public Object getProxy() {
		  //java.lang.reflect package Class Proxy class
		  //Classloader -- classloader
		  ClassLoader loader=this.getClass().getClassLoader();
		  //Class<?> [] interfaces --- reflection object of the interface
		  Class[] interfaces=this.targetObject.getClass().getInterfaces();
		  //InvocationHandler h---this
		  return Proxy.newProxyInstance(loader, interfaces, this);
	  }

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		return method.invoke(targetObject, args);
	}

}
package com.wangxing.test5;

public class Main {

	public static void main(String[] args) {
		huoCheZhan  hcz=new huoCheZhan();
		hcz.maipiao();
		ProxyObject  proxyobj=new ProxyObject(hcz);
		//Proxy class object
		SellPiao dsd=(SellPiao) proxyobj.getProxy();
		dsd.maipiao();
	}
}


      CGlib agent ---- CGlib is a third development package. You need to download and import it into the project in advance
     [all java classes provide proxy class objects]
For example:
  1. Create a class that requires a proxy

package com.wangxing.test6;

public class huoCheZhan{
	public void maipiao(){
		System.out.println("This is the railway station. I'm selling tickets");
	}
}

2. Create and obtain proxy objects

package com.wangxing.test6;

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 ProxyObject implements MethodInterceptor{
	  //Define target object
	  private  Object targetObject;
	  
	  public ProxyObject(Object targetObject){
		  this.targetObject=targetObject;
	  }
	  
	  //Get proxy object
	  public Object getProxy() {
		 Enhancer enhancer=new Enhancer();
		 enhancer.setSuperclass(targetObject.getClass());
		 enhancer.setCallback(this);
		 return enhancer.create();
	  }

		@Override
		public Object intercept(Object proxy, Method arg1, Object[] params, MethodProxy methodProxy) throws Throwable {
			return methodProxy.invokeSuper(proxy, params);
		}
}

3. Test

package com.wangxing.test6;

public class Main {

	public static void main(String[] args) {
		huoCheZhan  hcz=new huoCheZhan();
		ProxyObject  proxyobj=new ProxyObject(hcz);
		//Proxy class object
		huoCheZhan daili=(huoCheZhan) proxyobj.getProxy();
		daili.maipiao();
	}
}

Comparison:
1. Static proxy is to explicitly define a business implementation class and a proxy in the code, wrap the business method with the same name in the proxy class, and the user calls the wrapped business method through the proxy class;
Manually create a subclass with the same interface as the target class and wrap the target class.
2.JDK dynamic proxy calls the method of the same name of the class in the dynamically generated proxy class through the method name in the interface. [brother mode]
Through the Proxy class in the reflection package provided by jdk, dynamically create a subclass object that implements the same interface as the target class to wrap the target.
3.CGlib dynamic proxy inherits the business class. The generated dynamic proxy class is a subclass of the business class, and proxy by rewriting the business method. [parent-child mode]
Through the Enhancer class provided by CGlib, dynamically create a subclass object of the target class to wrap the target class.

Static proxy     JDK dynamic agentCGlib dynamic proxy
Create proxy classes manuallyDynamically generate proxy class objects     Dynamically generate proxy class objects
The Proxy class in the reflection package provided by jdkThe Enhancer class provided by CGlib
Proxy objects can only be created for Java classes that implement interfacesCreate a proxy object for any Java class

Keywords: Java Back-end

Added by dhorn on Wed, 08 Dec 2021 13:59:17 +0200