[java] simple implementation of proxy mode

concept

Proxy Pattern is a structural design pattern that allows you to provide alternatives or placeholders for objects. The agent controls access to the original object and allows some processing before and after the request is submitted to the object. In the proxy mode, one class represents the functions of another class. We create objects with existing objects to provide functional interfaces to the outside world.

objective

  • Control access: provides a proxy for other objects to control access to this object.
  • Function enhancement: when the call of the target object is completed, some additional functions can be added.

problem

Why control access to an object? For example: there is such a huge object that consumes a lot of system resources. You only need to use it occasionally, not always.

resolvent

The middle layer is added, and the key code implementation is combined with the proxy class.

Create a new proxy class that is the same as the original service object interface, and then update the application to pass the proxy object to all original object clients. After receiving the client request, the proxy class will create the actual service object and delegate all work to it.

Practical application

1. Shortcuts in Windows to connect to real applications.

2. Buying a car doesn't go directly to the car factory, but to the 4s store.

3. spring aop (slice oriented programming).

Specific examples:

Credit card is the agent of bank account, and bank account is the agent of a large bundle of cash. They all implement the same interface and can be used for payment. Consumers will be very satisfied because they don't have to carry a lot of cash with them; Store owners will also be very happy because the transaction income can be electronically entered into the store's bank account without worrying about the loss of cash or robbery when depositing.

Implementation mode

1. Static proxy

Case realization steps

(1) Create an interface to define the method of selling u disk.

public interface UsbSell {
 // Functions to be realized by manufacturers and businesses (selling U SB flash drives)
    float sell(int amount);
}

(2) Create factory class

// The manufacturer does not accept the separate purchase of users and needs the merchant to sell as an agent
public class UsbFactory implements UsbSell {

    @Override
    public float sell(int amount) {
        return 85.0f * amount;  // Ex factory price
    }
}

(3) Create merchant class (agent class)

public class TaoBao implements UsbSell {
    // Which manufacturer does the merchant represent
    private UsbSell factory = new UsbFactory();

    @Override
    public float sell(int amount) {
        float price = factory.sell(amount);
        float finalPrice = price + 25; // Function enhancement
        System.out.println("A treasure will return you a 5 yuan coupon!!!");
        return finalPrice;  // price
    }
}

The price change operation cannot be accessed and used by consumers, and the object of action can only be merchants (wechat merchants, physical stores, etc.).

(4) Create test class (ordinary consumer)

public class shopMain {
    public static void main(String[] args) {
        TaoBao tb = new TaoBao();
        float pay = tb.sell(3);
        System.out.println("You purchased U Price of Taobao: "+ pay + 'element');
    }
}

Output result:

3x 85+25 = 280, no error after checking calculation.

shortcoming

  • When the target class increases, the agent class also needs to be added (for example, if a factory class is created in the above example, this class can only represent one brand factory. When factories of other brands are established, an agent class needs to be created for this factory).
  • When interface methods are added or modified, many classes need to be modified.

(2) Dynamic agent

Meaning: relying on the reflection mechanism of jdk, the ability to create objects is to create objects of proxy class. We don't need to create proxy class.

The dynamic agent will dynamically create class bytecode and load it into JVM memory during JDK operation. There are two common implementation methods: using JDK agent and using cglb dynamic agent.

JDK proxy implementation

In this part, we need to understand that the classes and interfaces in java reflection package realize the function of dynamic Proxy, and the reflection package Java There are three classes in lang.reflect: InvocationHandler, Method and Proxy.

  • InvocationHandler interface: indicates what the agent wants to do (defines the function to be completed by the target class).
  • Method: the method in the target class. jdk is responsible for providing the method object.
  • Proxy: use the static method of proxy class to create proxy object and convert the return value to interface type.

(1) Create interface

public interface UsbSell {
    float sell(int amount);
}

(2) Create factory class (target class)

public class UsbFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        return 85.0f * amount;  // Ex factory price
    }
}

(3) create the implementation class of InvocationHandler interface

//InvocationHandler interface must be implemented to complete the functions of proxy class (calling target method, function enhancement)
public class MySellHandler implements InvocationHandler {
    private  Object target = null;
    //The target object of dynamic proxy is dynamically passed in, and the proxy will be created for whoever passes it
    public MySellHandler(Object target){
        this.target = target;
    }
    //args represents the parameters of the sell method in the interface
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res = null;
        res = method.invoke(target,args);
        if(res!=null){
            Float price = (Float)res;
            price = price+25;
            res = price;
        }
        System.out.println("A treasure will return you a 5 yuan coupon!!!");
        return res;
    }
}

(4) Write test class

public class Test {
    public static void main(String[] args) {
        //Create target object
        UsbSell usbFactory = new UsbFactory();
        //Create invocationHandler object
        InvocationHandler invocationHandler = new MySellHandler(usbFactory);
        //Create proxy object
        UsbSell proxy= (UsbSell) Proxy.newProxyInstance(
                usbFactory.getClass().getClassLoader(),
                usbFactory.getClass().getInterfaces(),
                invocationHandler
        );
        System.out.println("You purchased U Price of Taobao:"+ proxy.sell(100) + 'element');
    }
}

Output result:

Unlike static proxies, we no longer need specific implementation classes for each factory (such as TaoBao.java). When adding a method, you only need to modify the interface and target class files, and the client class (Test.java) can be called by Proxy object. Note that the dynamic Proxy of jdk must have an interface, and the target class must implement the interface.

reference resources: Design mode (agent mode) |  Agent design pattern

Keywords: Java

Added by hostcord on Fri, 28 Jan 2022 20:40:14 +0200