preface

This is the 8th day of my participation in the First Challenge 2022

Smart people find design patterns everywhere in the process of writing code, and design patterns are also solutions to common problems faced by software developers in the process of software development. Great wisdom in line with the purpose of “happy alone is better than all happy” to share with you the learning experience of design mode.

When writing code, we sometimes encounter situations where the access object is not suitable or cannot directly reference the target object. For example, on the Intranet, for security reasons, we need to shield the client from directly accessing the real object. What should we do in this situation? Start your smart little brain thinking ๐Ÿค”~~

Yes, that’s where the proxy model comes in.

The proxy pattern

First, a brief description of the proxy pattern. Definition of proxy mode: the proxy mode provides a proxy object to an object, and the proxy object controls the reference to the original object.

This definition seems to be not very easy to understand, so or in line with the purpose of “trivial problems will be obscene solution”, we will describe his definition of some more straightforward. Buy train ticket in this matter, for example, in 12306 before the app, a lot of people is to contact the scalpers to buy train ticket, cattle quite so we own agent, and through the cow to buy a ticket, we can avoid direct interaction with the railway station, can save a lot of things, and also can enjoy the scalpers better service (of course, money ๐Ÿ’ด or want to foot).

Next we will introduce another concept: static and dynamic proxies. In software development, we often divide the agent mode into static agent and dynamic agent. What is the difference between the two? Static proxy, as the name suggests, is static (nonsense ๐Ÿ˜œ), which is essentially a hand-written (or tool-generated) proxy class, that is, a compiled proxy class that exists before the program runs. However, if we need a lot of agents, creating each one would be too time-consuming and would involve a lot of repetitive code, we can choose dynamic agents. Dynamic agents can dynamically create proxy classes and instances to perform specific functions as needed during program execution.

To put it bluntly, the essential difference between static and dynamic proxies is when and how proxy classes are created.

As always, let’s look at the differences in code.

Static agent

Step 1: Create a service class interface

/ * * *@description: BuyTicket
 * @author: Zhuang Ba. Liziye *@create: in the 2021-08-10 s, when * * /
public interface BuyTicket {

    void buyTicket(a);
    
}
Copy the code

Step 2: Implement the service interface

/ * * *@description: BuyTicketImpl
 * @author: Zhuang Ba. Liziye *@create: the 2021-08-10 which * * /
public class BuyTicketImpl implements BuyTicket{

    @Override
    public void buyTicket(a) {
        System.out.println("I'd like to buy a train ticket."); }}Copy the code

Step 3: Create the proxy class

/ * * *@description: BuyTicketProxy
 * @author: Zhuang Ba. Liziye *@create: "* * / 2021-08-10
public class BuyTicketProxy implements BuyTicket {
    private BuyTicket buyTicket;

    public BuyTicketProxy(final BuyTicket buyTicket) {
        this.buyTicket = buyTicket;
    }

    @Override
    public void buyTicket(a) {
        System.out.println("Take the money and buy the tickets.");
        buyTicket.buyTicket();
        System.out.println("Took a train to Lhasa."); }}Copy the code

Finally, let’s write a test class and execute it

/ * * *@description: test
 * @author: Zhuang Ba. Liziye *@create: 2021-08-09 * * / news
public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
        BuyTicket buyTicket = new BuyTicketImpl();
        buyTicket.buyTicket();
        BuyTicketProxy buyTicketProxy = newBuyTicketProxy(buyTicket); buyTicketProxy.buyTicket(); }}Copy the code

We can see that static proxies can extend the functionality of the target object in accordance with the open closed principle, but we have to create proxy classes for each service, which is too much work to manage, and the proxy classes have to be modified as soon as the interface changes.

A dynamic proxy

In dynamic proxy we no longer need to manually create the proxy class, we just need to write a dynamic processor. The real proxy objects are created dynamically for us by the JDK at run time.

First we create a dynamic processor

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/ * * *@description: DynamicProxyHandler
 * @author: Zhuang Ba. Liziye *@create: "* * / 2021-08-10
public class DynamicProxyHandler implements InvocationHandler {

    private Object object;

    public DynamicProxyHandler(final Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Take the money and buy the tickets.");
        Object result = method.invoke(object, args);
        System.out.println("Took a train to Lhasa.");
        returnresult; }}Copy the code

Let’s write another test class

import java.lang.reflect.Proxy;

/ * * *@description: DynamicProxyTest
 * @author: Zhuang Ba. Liziye *@create: the 2021-08-10 thus * * /
public class DynamicProxyTest {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicketImpl();
        BuyTicket proxyBuyTicket = (BuyTicket) Proxy.newProxyInstance(BuyTicket.class.getClassLoader(), new
                Class[]{BuyTicket.class}, newDynamicProxyHandler(buyTicket)); proxyBuyTicket.buyTicket(); }}Copy the code

One thing to note here is that the proxy.newProxyInstance () method takes three arguments:

  • ClassLoader: specifies the ClassLoader used by the current target object. The method for obtaining the loader is fixed
  • Class
    [] interfaces: Specifies the type of the interface implemented by the target object, using generics to confirm the type
  • InvocationHandler: Specifies the dynamic handler that fires the event handler method when executing the target object’s method

Compared to static proxies, we can see that dynamic proxies greatly reduce our development tasks, reduce the dependence on business interfaces, and reduce coupling. In addition, we found that the proxyBuyTicket class inherits from the java.lang.Reflect. Proxy class, which is why the JDK dynamic Proxy mechanism does not implement dynamic Proxy to classes: Java only allows single inheritance.

summary

We can buy tickets directly at the train station by ourselves, so in software development, methods can be directly called to complete the function, why must through the agent? The reason is that using proxy mode can effectively decouple the concrete implementation (ticket buying process) from the caller (ticket buyer), and completely hide the concrete implementation (ticket buying process) internally (scalper) through interface-oriented coding. In addition, a proxy class is not only an intermediary that separates the client from the target class, it can also be used to add functionality without modifying the original code, which is a typical application of the open closed principle.

In fact, the real business functions are implemented by the target class, and the proxy class is only used to extend and enhance the behavior of the target class. For example, if we need to add logging at a later stage of a project, we can use proxies to do this without directly modifying the encapsulated target class.

My experience is limited, some places may not be particularly in place, if you think of any questions when reading, welcome to leave a message in the comments section, we will discuss one by one ๐Ÿ™‡

Please take a thumbs up and a follow (โœฟโ—กโ€ฟโ—ก) for this article ~ a crab (โ—’โ—ก’โ—)

If there are mistakes in the article, welcome to comment correction; If you have a better, more unique understanding, you are welcome to leave your valuable ideas in the comments area.

Love what you love, do what you do, listen to your heart and ask nothing