java design pattern agent

What is proxy mode?

In fact, "agent" means the same thing as "agent" in life. Simply put, it means that what you want to do cannot be done directly due to some reasons, and must be implemented by someone else "on behalf of". There are many examples, so I won’t give any examples. The point is to understand what it does and how it does it. As for when to use it, it’s up to you to decide.

static proxy

Let's first get a preliminary understanding of the proxy mode through a simple example of a static proxy.
Scenario: It’s like a headhunter recruiting people for a company. The company is the "real role" that recruits people, and the headhunter is the "agent role" that is responsible for recruiting people.

Agent content is abstracted into an interface

The company and the headhunter need to mutually agree on the scope of the agency's responsibility (specifically what things will be done).

/**
 * 描述:定义代理的具体内容
 * <p>作者: aliyu
 * <p>创建时间: 2021-10-15 10:44 上午
 */
public interface HireSomeone {
    
    

    /**
     * 雇佣
     */
    public void hire();
}

real character

The person who actually handles the request - the company. The proxy content interface ultimately needs to be implemented by the company itself.

/**
 * 描述:公司招聘,实际招聘人
 * <p>作者: aliyu
 * <p>创建时间: 2021-10-15 10:37 上午
 */
public class CompanyHire implements HireSomeone{
    
    

    @Override
    public void hire() {
    
    
        System.out.println("我是实际执行雇佣的人");
    }
}

agent role

The agent role contains references to real objects, so that requests can be converted into real objects for processing, and operations can be attached before and after (for example: the person looking for a job has agreed to join the job, and the headhunter needs to send him an acceptance email. This operation, the headhunter In fact, it cannot be handled. Therefore, the headhunter needs to recruit the HR of the specific company, and the HR will complete this operation. At the same time, the headhunter, as a middleman, can add some things to the exchanges between the two parties).

/**
 * 描述:代理角色
 * <p>作者: aliyu
 * <p>创建时间: 2021-10-15 10:54 上午
 */
public class ProxyHire implements HireSomeone{
    
    

    /**
     * 传入实际操作的角色“公司”
     */
    private CompanyHire companyHire;

    public ProxyHire(CompanyHire companyHire) {
    
    
        this.companyHire = companyHire;
    }

    @Override
    public void hire() {
    
    
        //实际操作是由真实角色“公司”完成的
        companyHire.hire();
    }
}

The test proxy object completes the proxy:

/**
 * 描述:模拟通过调用代理对象,实际调用真实对象的过程
 * <p>作者: aliyu
 * <p>创建时间: 2021-10-15 10:57 上午
 */
public class TestProxy {
    
    
    
    public static void main(String[] args) {
    
    
        //实例化"实际对象"
        CompanyHire companyHire = new CompanyHire();
        //传入"代理"
        ProxyHire proxyHire = new ProxyHire(companyHire);
        //点进去看代码,可以发现"雇佣"操作实际是由传入"真实对象"完成的。
        proxyHire.hire();
    }
}

dynamic proxy

Each proxy class must implement the proxy content interface. If methods are added to the interface, the proxy class must also be modified accordingly. Secondly, each interface object of the proxy class corresponds to a real object. If there are many real objects, the static proxy class will be very bloated and difficult to handle. As shown below:

public class ProxyHire implements HireSomeone{
    
    

    private CompanyHire companyHire;
......

public class ProxyHire2 implements HireSomeone{
    
    

    private CompanyHire2 companyHire2;
......

public class ProxyHire3 implements HireSomeone{
    
    

    private CompanyHire3 companyHire3;
......

At the same time, we can also find that such code is actually repeated. Is there any way not to write so many proxy classes? This brings us to dynamic proxy.
Dynamic proxies are different from static proxies in that they dynamically create proxy classes based on the proxy objects. In this way, you can avoid the problem of too many proxy classes in static proxies. Dynamic proxy is an implementation method, which is implemented through reflection. It is generated through fixed rules with the help of Java's own java.lang.reflect.Proxy.

new a dynamic proxy class:

/**
 * 描述:动态代理类
 * <p>作者: aliyu
 * <p>创建时间: 2021-10-15 2:09 下午
 */
public class DynamicProxyHire implements InvocationHandler {
    
    

    /**
     * 传入的是object,就可以满足不同真实对象的传入
     */
    private Object object;

    public DynamicProxyHire(Object object) {
    
    
        this.object = object;
    }

    /**
     * 当在与其关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
     * 简单来说就是通过动态代理类执行真实对象方法时,会进入这里。
     * @param proxy 真实对象
     * @param method 通过代理对象调用的方法(通过反射获得)
     * @param args  参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        //调用真实对象的方法
        Object result = method.invoke(this.object, args);
        return result;
    }
}

Testing complete proxying via dynamic proxy objects

public class TestDynamicProxy {
    
    
    
    public static void main(String[] args) {
    
    
        //我们要代理的真实对象
        CompanyHire companyHire = new CompanyHire();
        //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
        InvocationHandler handler = new DynamicProxyHire(companyHire);
        //第一个参数 ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
        ClassLoader classLoader = handler.getClass().getClassLoader();
        //第二个参数,我们这里为代理对象提供的接口是真实对象所实现的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
        Class<?>[] interfaces = companyHire.getClass().getInterfaces();
        //第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
        //表示当前的InvocationHandler实现实例对象
        HireSomeone hireSomeone = (HireSomeone) Proxy.newProxyInstance(classLoader, interfaces, handler);
        hireSomeone.hire();
    }
}

Proxy model advantages and disadvantages

Advantage 1 - Lazy loading

"When the system starts, the methods that consume the most resources are separated using the proxy mode, which can speed up the startup of the system and reduce the user's waiting time. When the user actually queries the operation, the proxy class will load the real data separately
. The database query class completes the user's request. This process uses the proxy mode to realize lazy loading. The theory is understandable, but how is it implemented? Found an example.

Abstract proxy interface:
Insert image description here
Real role:
Insert image description here
Proxy role:
Insert image description here
ps: It turns out that you only need to set the incoming real object = null. Then when the method is actually called, the real object is instantiated. This plays the role of lazy loading.
Example URL: https://www.cnblogs.com/klyjb/p/11522968.html

Advantage 2-Reduced coupling and easy maintenance

The verification work is done before calling the real object. If new functions are added, the proxy object can be modified instead of the real object. Object aggregation replaces inheritance and reduces coupling.

The so-called "verification work can be done before calling the real object" is because it is the method of calling the real object in the proxy object method. It is not difficult to add a few lines of verification code to it.

    @Override
    public void hire() {
    
    
        //这里可以加入校验代码
        //实际操作是由真实角色完成的
        companyHire.hire();
        //执行完后也可以加入代码,实现某些特殊的需求
    }

"If a new function is added, you can modify the proxy object instead of the real object." - This sentence is probably the same as adding verification before calling the real object, but the added content is different.
In short, this can be done, but I have never encountered such a scenario and cannot explain clearly.

shortcoming

Each proxy class must implement the proxy content interface. If methods are added to the interface, the proxy class must also be modified accordingly.

other

Guess you like

Origin blog.csdn.net/mofsfely2/article/details/120777762