Agent mode of java design pattern (7)

Don't lose your temper at will. In life, it is impossible for a person to become friends with everyone he knows. A true friend cannot be forced, and God does not stipulate who must be friends with whom. Everything must be reluctant to do, and everything in life can be reluctant. Only "love" cannot be reluctant, and friendship is the same.

Design pattern learning, I will blog about 23 design patterns in the near future , so stay tuned~
—1/9/2021

definition

Provide a proxy for other objects to control access to this object. In some cases, an object is not suitable or cannot directly refer to another object, and the proxy object can play an intermediary role between the client and the target object.

Baidu Encyclopedia

Role classification

  • Abstract role: A business method implemented by an interface or abstract class that declares a real role.
  • Agent role: Realize abstract role, which is the agent of real role. The abstract method is realized through the business logic method of real role, and you can attach your own operations.
  • Real role: implement abstract roles, define the business logic to be implemented by real roles, for agent roles to call

analysis

Suppose I want to rent a house, I must first go to an agency to see the house, and then choose a suitable house to rent;

Where did the house come from? It must be the landlord, right?

Here the landlord is a person who needs an agent, and the agent is the house, so let the house agent be an agent, let the agent help us rent it out.

benefit:

  • The landlord has not changed anything, but the house is represented by the agency, and the agency will rent the house to us after getting the house, and collect agency fees, etc.

UML类图(1.1):


analysis:

  • The real role of HouseMaster refers to the landlord here
  • IHouse abstract role refers to the house here
  • HouseProxy agent role here refers to intermediary

Static proxy implementation:

IHouse (house):

public interface IHouse {
    
    
    void showHouse();
}

HouseMaster (Host):

public class HouseMaster implements IHouse {
    
    

    @Override
    public void showHouse() {
    
    
        Log.i("代理模式:", "我是房东,我要出租房");
    }
}

HouseProxy (intermediary):

public class HouseProxy {
    
    

    IHouse house;
    //吧房子交给中介 (吧IHouse 接口组合到 HouseProxy 上)
    public HouseProxy( IHouse house) {
    
    
        this.house = house;
    }

    public void showHouse(){
    
    
        house.showHouse();//房东的房子
    }

}

Use code:

//创建代理类 传入需要代理的类
HouseProxy houseProxy = new HouseProxy(new HouseMaster());

houseProxy.showHouse();

Log图(2.1):


Maybe everyone is still fascinated by the agency model, I will explain in detail

Now, we only use HouseProxy (intermediary) to see the house of landlord A, he can also do other operations, for example, we can let him take us to see other houses, and we can also tip the agent:

HouseProxy (intermediary) class:

public class HouseProxy {
    
    

    IHouse house;
    public HouseProxy( IHouse house) {
    
    
        this.house = house;
    }

    public void showHouse(){
    
    
        money();//收取消费
        house.showHouse();//房东的房子
        seeHouse();//带用户看房
    }
    public void money(){
    
    
        Log.i("代理模式:","我是中介,我要收取消费");
    }
    public void seeHouse(){
    
    
        Log.i("代理模式:","我是中介,我带用户看房");
    }
}

Log图(2.2):


房东并没有发生变化,变化的只是中介
比如说在项目中,一个类用到了很多地方现在让这个这个类前面输出一句话,
咋们是不是就可以不在改变原有代码的基础上来达到这句话的显示呢?

Summary of static proxy mode:

advantage:

  • No change to the original code, meeting the opening and closing principle (closed for modification)
  • The public code is handed over to the agent class to realize the division of labor
  • Don't care about other affairs that are not your responsibility, and complete a completed transaction through the later agent. The incidental result is that the programming is simple and clear.

Disadvantages:

  • One class needs to create a proxy class, the amount of code will double, and the development efficiency will be reduced

Dynamic proxy mode

Dynamic proxy refers to: the proxy class can change with the change of the proxy.

Simply put, I want A to be proxied, just A proxy, I want B to be proxied by B, without creating many proxy classes

Roles:

  • InvocationHandler call handler
  • Proxy

What is InvocationHandler?

JDK1.8CHW图(3.1):


JDK1.8CHW download Extraction code: lfoz

InvocationHandler is an interface implemented by the invocation handler of the proxy instance .


InvocationHandler is an interface that needs to be rewritten to
invoke(Object proxy, Method method, Object[] args) method

Invoke method explanation:

  • Parameter one (Object proxy): the proxy instance that calls the method
  • Parameter two (Method method): The declared class of the method object will be the interface declared by the method, and it can be the super interface of the proxy class inheriting the method's proxy interface. (It doesn't matter if you don't understand here)
  • Parameter three (Object[] args): The array of objects containing the method call passing the parameter values ​​of the proxy instance, or null if the interface method has no parameters. Parameters of primitive types are contained in instances of appropriate primitive wrapper classes, such as java.lang.Integer or java.lang.Boolean.

This is the explanation in jdk: it doesn't matter if the method explanation here is not clear.

JDK1.8CHW图(3.2):

What is Proxy?

JDK1.8CHW图(3.3):


Proxy provides static methods for creating dynamic proxy classes and instances. It is also the superclass of all dynamic proxy classes created by these methods. (Official words)

My understanding: Proxy is to obtain an instance of the proxy

You definitely don't want to read so many words. Simply put: Proxy works with InvocationHandler to complete the automatic generation of proxy classes.

If you get the proxy instance:

Proxy.newProxyInstance(
		ClassLoader loader,
        Class<?>[] interfaces,
        InvocationHandler h);

Proxy.newProxyInstance parameter analysis:

  • Parameter 1: The location of the loaded class
  • Parameter two: proxy interface
  • Parameter 3: Represent itself: InvocationHandler

Code:

ProxyInvocationHandler类:

public class ProxyInvocationHandler implements InvocationHandler {
    
    

    Object object;

    //参数一:object 具体接口的实现类
    public ProxyInvocationHandler(Object object) {
    
    
        this.object = object;
    }

    //生成代理类  返回的是被代理的接口 (返回的是object接口)
    public Object getProxy(){
    
    
        /**
         * this.getClass().getClassLoader() 加载类所在位置
         * object.getClass().getInterfaces() 代理的接口
         * this  表示本身:InvocationHandler
         */
       return Proxy.newProxyInstance(
			       this.getClass().getClassLoader(),
			       object.getClass().getInterfaces(),
			       this
	     	 );
    }

    /**
     * @param proxy 调用该方法的代理实例
     * @param method  所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
     * @param args 包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。
     *             原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
     * @return
     * @throws Throwable
     */
    @Override  //处理代理实例,返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        Object invoke = method.invoke(object, args);
        return  invoke;
    }
}

use:

//需要代理 真实角色
HouseMaster houseMaster = new HouseMaster();

//代理类生成器  传入需要代理的类
ProxyInvocationHandler pit =
			 new ProxyInvocationHandler(houseMaster);

//生成代理类 (必须返回接口)
IHouse proxy = (IHouse) pit.getProxy();

//输出租房子
proxy.showHouse();

Log图(2.3):


HouseMaster (proxy class) automatically generates the corresponding IHouse (interface) through the reflection mechanism of the ProxyInvocationHandler (call handler) class

note:


Use the reflection mechanism of InvocationHandler to get the currently called method:

public class ProxyInvocationHandler implements InvocationHandler {
    
    

	.....
	
    @Override  //处理代理实例,返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        msg(method.getName());
        Object invoke = method.invoke(object, args);
        return  invoke;
    }

    public void msg(String msg){
    
    
        Log.i("代理模式","代理了"+ msg +"方法");
    }
}

流程图(4.1):


Here is the name of the showHouse() method obtained

Log图(2.4):

Now this ProxyInvocationHandler is a public proxy class, passed in a class that needs a proxy, and then an object of proxy class can be returned through getProxy() (provided that the passed proxy class implements the returned proxy class)

advantage:

  • No change to the original code, meeting the opening and closing principle (closed for modification)
  • The public code is handed over to the agent class to realize the division of labor
  • The dynamic proxy agent is an interface, generally a corresponding business
  • A dynamic proxy can proxy multiple interfaces, as long as it implements the same interface. Compared with the static proxy, each proxy class needs to create a proxy class, which is more flexible

If you really don't understand this article, you can use it, because the dynamic code is relatively fixed!

Just know that each class plays a corresponding role and will be used.

  • ProxyInvocationHandler call handler (used to automatically generate proxy classes)

  • The real role of HouseMaster (need to be represented (this article refers to the landlord renting the house))

  • IHouse abstract role (here refers to the house)

  • pit.getProxy() returns the abstract role (here refers to returning to the house)

  • proxy.showHouse(); specific implementation (referring to renting a house)

Complete project

Go to the Design Patterns/Design Principles homepage

Originality is not easy, your likes are your greatest support for me, please like to support me~

Guess you like

Origin blog.csdn.net/weixin_44819566/article/details/112390541