Design pattern --- agent pattern

Posted by nareshrevoori on Sat, 04 Sep 2021 04:17:54 +0200

Static proxy

An object provides a proxy with a fixed role to control access to the object. Proxy classes and delegate classes have a common parent class or parent interface, so proxy objects can be used wherever delegate objects are used. The agent class is responsible for request preprocessing, filtering, assigning requests to the delegate class for processing, and subsequent processing after the delegate class executes the request.

Example: Xiao Ming wants to chase Xiao Hong now, but he is shy and dare not chase Xiao Hong directly. He chases Xiao Hong through Xiao Dai. At this time, Xiaoming is the proxy class, and xiaodai is the proxy class. Because Xiaoming wants xiaodai to send dolls, flowers and chocolates, xiaodai must also have these behaviors, so Xiaoming and xiaodai are integrated into the same interface.

Public behavior of the most demanding and agent:

/**
 * Method to be executed by the most demanding person
 * Both the proxy class and the proxy class should integrate the same interface, so that when the proxy class executes the method, the proxy class executes the same method and strengthens the methods to be executed by the proxy class.
 */
public interface GiveGirl {
    void giveDolls(); // Send dolls
    void giveFlowers(); // Send flowers
    void givechocolate(); // Send Qiao Ke Li
}

The person pursued is Xiao Hong

public class SchoolGril {
    private String name;

    public SchoolGril(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

The person who pursues, that is, Xiao Ming, realizes specific behavior.

/**
 * The pursuer, that is, the agent, pursues his girlfriend through being pursued
 */
public class Pursuit implements GiveGirl {
    SchoolGril schoolGril;

    public Pursuit(SchoolGril schoolGril) {
        this.schoolGril = schoolGril;
    }


    @Override
    public void giveDolls() {
        System.out.println(schoolGril.getName() + "," + "Give you a doll" );
    }

    @Override
    public void giveFlowers() {
        System.out.println(schoolGril.getName() + "," + "Send you flowers" );
    }

    @Override
    public void givechocolate() {
        System.out.println(schoolGril.getName() + "," + "Give you chocolate" );
    }
}

The static proxy class, that is, xiaodai, also implements the behavior interface. After all, you are an agent and can't fully perform the work of the principal Xiaoming. What can you do.

public class StaticProxy implements GiveGirl {

    //If the object of the agent is an agent, there must be an agent
    Pursuit pursuit;

    //Incoming agents need suitors
    public StaticProxy(SchoolGril schoolGril) {
        pursuit = new Pursuit(schoolGril);
    }

    @Override
    public void giveDolls() {
        //The place where the proxy object is processed before execution

        pursuit.giveDolls();

        //The place where the proxy object is processed after execution
    }

    @Override
    public void giveFlowers() {
        //The place where the proxy object is processed before execution

        pursuit.giveFlowers();

        //The place where the proxy object is processed after execution
    }

    @Override
    public void givechocolate() {
        //The place where the proxy object is processed before execution

        pursuit.givechocolate();

        //The place where the proxy object is processed after execution
    }
}

Test class

public class TestStaticProxy {
    public static void main(String[] args) {
        SchoolGril schoolGril = new SchoolGril("lisa");
        StaticProxy staticProxy = new StaticProxy(schoolGril);

        //The method executed by the proxy will be hidden by the proxy object
        staticProxy.giveDolls();
        staticProxy.giveFlowers();
        staticProxy.givechocolate();
    }
}

Dynamic agent

Compared with static proxy, dynamic proxy is more flexible in creating proxy objects. The bytecode of dynamic proxy class is dynamically generated by Java reflection mechanism when the program is running. It will dynamically create proxy objects for the target object during the program run-time through the reflection mechanism, without the need for programmers to write its source code manually. Dynamic agent not only simplifies programming, but also improves the scalability of software system, because reflection mechanism can generate any type of dynamic agent class. The behavior of an agent can represent multiple methods, which not only meets the needs of production, but also achieves the purpose of common code.

Two implementations of dynamic agent:

  1. JDK dynamic agent

  2. CGLIB dynamic proxy

The proxy class, that is, the small generation, needs to implement the InvocationHandler interface

/**
 * proxy class
 */
public class DynamicProxy implements InvocationHandler {

    // The type of the target object is not fixed and is generated dynamically when it is created
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    /**
     *  1,Call the method of the target Object (return Object)
     *  2,Enhance the behavior of the target object
     * @param proxy The proxy instance that called the method
     * @param method  Method of target object
     * @param args  Method parameters of the target object
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Enhanced behavior
        System.out.println("==============Execute before method");

        // Call the method of the target Object (return Object)
        Object result = method.invoke(target,args);

        // Enhanced behavior
        System.out.println("Execute after method==============");
        return null;
    }

    /**
     * Get proxy object
     * public static Object newProxyInstance(ClassLoader loader,
     *                                       Class<?>[] interfaces,
     *                                       InvocationHandler h)
     *      loader: Class loader
     *      interfaces: Interface array
     *      h: InvocationHandler Interface (implementation class of InvocationHandler interface passed in)
     *
     *
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
}

Proxy.newProxyInstance() is the method to create a proxy object.

Test class

public class TestDynamicProxy {
    public static void main(String[] args) {
        SchoolGril schoolGril = new SchoolGril("Mary");
        Pursuit pursuit = new Pursuit(schoolGril);
		
		//Pass in the object to be represented, Xiao Ming
        DynamicProxy dynamicProxy = new DynamicProxy(pursuit);
       	//Gets the object of the proxy, xiaodai
        GiveGirl proxy = (GiveGirl) dynamicProxy.getProxy();
        proxy.giveDolls();

    }
}

Topics: Java Design Pattern