Design Patterns - Agent Patterns

Keywords: jvm Java Programming

Definition of proxy pattern: The proxy pattern provides a proxy object for an object, and the proxy object controls the reference of the original object. For example, one person or institution acts on behalf of another person or institution. In some cases, a client does not want or can not directly refer to an object, while a proxy object can act as a mediator before the client and the target object.

Examples of application scenarios:

Through the above description of the agent model, we can know that the purpose is to control the object reference. In the life scenario, we take buying a car as an example. If we want to buy a car, we must go through the 4S shop, which is to act as an agent. The purpose is to control the buying behavior of the customers, and we must go through the 4S shop to buy a car from the automobile manufacturer.

1. First, build a new interface to buy a car.

public interface IBuyCar {
    //buy a car
    void buyCar();
}

2. Declare a customer who wants to buy a car and realize the interface of buying a car.

public class Customer implements IBuyCar {

    private int cash;//Car purchase

    public int getCash() {
        return cash;
    }

    public void setCash(int cash) {
        this.cash = cash;
    }

    @Override
    public void buyCar() {
        Log.e("buyCar", "It's expensive to buy a car.-->" + cash + "element");
    }
}

3. Declare that a 4S car shop, which is a car buying agent, also realizes the car buying interface and must accept orders from customers.

public class BuyCarProxy implements IBuyCar{
    private Customer customer;//Receiving Car Buyers

    public BuyCarProxy(Customer customer){
        this.customer=customer;//Receiving Car Buyers
    }

    @Override
    public void buyCar() {//Achieving the Purchase of Cars for Customers
        customer.buyCar();
    }
}

4. Create a client to simulate a car purchase.

  Customer customer=new Customer();
  customer.setCash(120000);
  BuyCarProxy buyCarProxy=new BuyCarProxy(customer);
  buyCarProxy.buyCar();

5. Implementing authority control through proxy mode

Through the above example, we may have a question, can't we go directly to the manufacturer to buy a car? Of course, if the implementation class can meet the requirements in the use scenario, we can directly implement the class, but when the implementation class can not meet the requirements, to expand the requirements, according to the open-close principle, you can not modify the implementation class code, then you use the proxy class. For example, when we buy a car, we need to check the purchase fee of the customer. If we meet the requirements, we will buy the car. If we do not meet the requirements, we will inform the customer that the purchase fee is insufficient.

 @Override
    public void buyCar() {//Achieving the Purchase of Cars for Customers
        int cash=customer.getCash();
        if(cash<100000){
            Log.e("buyCar","You don't have enough money to buy a car.");
            return;
        }
        customer.buyCar();
    }

Implementation scenario

Customer customer=new Customer();
customer.setCash(120000);
BuyCarProxy buyCarProxy=new BuyCarProxy(customer);
buyCarProxy.buyCar();

Customer customer1 =new Customer();
customer1.setCash(90000);
BuyCarProxy buyCarProxy1 =new BuyCarProxy(customer1);
buyCarProxy1.buyCar();

Dynamic proxy mechanism:

All of the above are the static implementation of proxy mode. The so-called static proxy is that it writes a proxy class for the class to be proxied by itself or generates the proxy class for it by tools. In short, it is the compiled proxy class that exists before the program runs, which sometimes feels very troublesome and leads to very inflexible. Compared with static proxy, dynamic proxy is stronger. Flexibility, because it does not need to specify a proxy class to proxy which proxy object when we design and implement it, we can defer this specification until the program runs, which is implemented by JVM.

Example: Or follow the example above

1.) First, we declare a dynamic proxy class to implement the InvocationHandler interface.

public class DynamicProxy implements InvocationHandler {

    // Instances of proxy classes
    Object obj;

    // Pass an instance of the agent into the constructor of the dynamic proxy class
    public DynamicProxy(Object obj) {
        this.obj = obj;
    }

    /**
     * Override invoke() method in InvocationHandler interface
     * More importantly, the dynamic proxy model allows us to keep the existing code structure unchanged.
     * In this case, the original "real method" can be extended, enhanced and achieved.
     * To control the behavior of the proxy object, the following before and after means that we can make special actions
     * Extension points for code entry.
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        /*
         * before : doSomething();
         */
        Object result = method.invoke(this.obj, args);

        /*
         * after : doSomething();
         */
        return result;
    }
}

2. Realization

        //The Real Object We Want to Act for
        Customer customer = new Customer();
        customer.setCash(10000);
        //If we want to proxy which real object, we pass it in and finally call its method through the real object.
        InvocationHandler handler = new DynamicProxy(customer);

        /*
         * Using Proxy's new Proxy Instance method to create our proxy object, let's look at its three parameters
         * The first parameter, handler.getClass().getClassLoader(), is used here to load our proxy object using the ClassLoader object of the handler class.
         * The second parameter is customer.getClass().getInterfaces(). The interface we provide here for the proxy object is the interface implemented by the real object, which means that I want to proxy the real object, so that I can call the methods in this group of interfaces.
         * The third parameter, handler, is the proxy object that we associate with the InvocationHandler above.
         */
        IBuyCar buyCar = (IBuyCar) Proxy.newProxyInstance(handler.getClass().getClassLoader(), customer.getClass().getInterfaces(), handler);
        buyCar.buyCar();

3. Dynamic Agent Benefits

Benefits of using Java dynamic proxy mechanism:

1. Reduce the workload of programming: If you need to implement a variety of proxy processing logic, as long as you write multiple proxy processors, you do not need to write a proxy class in each way.

2. Expansibility and maintainability of the system are enhanced, and it is much more convenient to modify the program (generally, it is only necessary to change the proxy processor class).

Conclusion:

Through the above application examples, we learned the specific usage scenarios of the proxy pattern.

Posted by themaxx113 on Sun, 19 May 2019 20:06:12 -0700