[learning notes] understand the design pattern in combination with the code - agent pattern (static agent, dynamic agent, extension)

Keywords: Java Design Pattern reflection Dynamic Proxy

Preface: notes based on Crazy God design mode video I. Dahua design pattern
(I've been updating my previous topic brushing blog recently. I've been updating a new blog for a long time today ~)

What is the proxy model

1, Introduction to agent model

Agent mode is a very common design mode. At the same time, there are many types. It is very necessary to learn it properly!

  • Definition: provides a proxy for other objects to control access to this object.
    It can be understood that a certain degree of indirectness is introduced when accessing objects, and this indirectness can add a variety of purposes.
  • UML diagram: agent composition, real role, agent and real color match inherit the common interface
  • For example, brokers (agents) and stars (real roles) inherit the "play receiving" interface. If you want to find a star to act, you have to "pick up the play" through the agent (imagine the star as the privatization object of the agent). In this way, brokers can add tasks such as screening and salary negotiation to their "play receiving" methods, and stars only need to pay attention to their own business.
  • In the above example, the benefits of agent mode are reflected. The real role is more specific, and in the expansion of the agent role, it also abides by the open and closed principle of OOP principle.
  • Classification of agent mode:
    1. Static proxy
    2. Dynamic agent (these two types are used and explained in combination with code below)
    3. Remote proxy: it provides local representation of an object in different address spaces, and is used to hide the fact that an object exists in different address spaces (such as calling methods of another PC)
    4. Virtual agent: used to store real objects that take a long time to instantiate, which can optimize performance. For example, when BiliBili is turned on, the Caton first displays the text, while the picture and video stream may be just a white box, and then gradually loaded. Here, a virtual agent is used
    5. Other categories such as security agent and intelligent guidance can be checked if you are interested

2, Static proxy mode

  • Role classification:
    1. Abstract role: interface or abstract class.
    2. Real role: the role represented
    3. Agent role: the agent of a real role usually adds some auxiliary operations.
    4. Customer: the person who accesses the agent role.
  • Benefits:
    1. Make the operation of real roles more pure without paying attention to some public businesses.
    2. The public business is entrusted to the agent role, which realizes the division of business
    3. When the public business is expanded, it is convenient for management
  • Disadvantages: a real role corresponds to a proxy role. The amount of code increases and the efficiency becomes low
  • Example code: landlord, intermediary, customer, rental (try to think about the corresponding roles above ~)
// ps: public class don't mind. Here I copy the codes of different files directly.
// 1. Public interface
public interface Rent {
    public void rent();
}

// 2. Landlord (real role)
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("Landlord: I want to rent a house");
    }
}

// 3. Intermediary (agent role)
public class MyProxy implements Rent {
    // Adopt "combination" mode
    private Host host;

    MyProxy() {
    }

    MyProxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        // You can add some more content, but the principal (proxy class) doesn't care about these things, just do their own thing.
        // Meet the open and closed principle
        System.out.println("Intermediary: take a look at the house");
        host.rent();
        System.out.println("Intermediary: signing contract");
    }
}

// 4. Customer: access agent role
public class Client {
    public static void main(String[] args) {
        // Just find an intermediary, regardless of the landlord
        Host host = new Host();
        MyProxy MyProxy = new MyProxy(host);
        MyProxy.rent();
    }
}

3, Dynamic agent mode

In order to solve the shortcomings of the above static proxy mode, there is a dynamic proxy mode ~
(it's not easy to understand this one, and I don't think it's detailed. I suggest you take another look at the video or other blogs.)

  • Principle: dynamic agent is implemented based on reflection mechanism.
  • Differences between and static agents:
    1. Static proxy: implement the interface, and then proxy through the instance of the interface implementation class.
    2. Dynamic proxy: create an instance of an interface class through reflection.
      (another principle is to create a clone with a construction method and an interface through reflection, and then generate an interface instance through the construction method of the clone)
  • Classes used:
    1. Proxy: provides static methods for creating dynamic proxy classes and instances
    2. InvocationHandler: each proxy instance has an associated calling handler. When calling the method of the proxy instance, it will be assigned to the invoke method of its calling handler.
  • Benefits:
    1. Benefits of static proxy
    2. A dynamic agent class represents an interface, which is generally a corresponding type of business. It avoids the disadvantages of static agent
  • Sample code: or an example of a landlord intermediary
// Inherits the InvocationHandler interface. At this time, this is an InvocationHandler
public class ProxyInvocationHandler implements InvocationHandler {
    
    // Proxy interface
    private Rent rent;
    
    public void setRent(Rent rent) {
        this.rent = rent;
    }
    
    // Generate proxy class
    public Object getMyProxy() {
        return Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }
    
    // The method invoke corresponding to InvocationHandler is used to process the proxy instance and return the result
    @Override
    public Object invoke(Object Proxy, Method method, Object[] args) throws Throwable {
        // Method is also a class under reflection package, which is related to reflection.
        System.out.println("Here comes the dynamic agent!");
        Object res = method.invoke(rent, args);
        return res;
    }
}

public class Client {
    public static void main(String[] args) {
        // Just find an intermediary, regardless of the landlord
        Host host = new Host();
        
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        // Put the proxied object
        proxyInvocationHandler.setRent(host);
        Rent proxy = (Rent)proxyInvocationHandler.getMyProxy();
        // In this case, we will execute invoke (in this case, the parameter Method is rent)
        // The proxy object executes the interface method and then assigns it to the invoke of the corresponding InvocationHandler
        proxy.rent();
    }
}
Universal template
  • Any interface can be used
public class BetterProxyInvocationHandler implements InvocationHandler {
    // 1. Proxy interface
    private Object target;

    // Set the proxy interface
    public void setTarget(Object target) {
        this.target = target;
    }

    // 2. Generate the proxy class
    public Object getProxy() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Yes " + method.getName() + " method");
        Object res = method.invoke(target, args);
        return res;
    }
}

Posted by bdlang on Sat, 25 Sep 2021 00:51:22 -0700