introduce

Proxy Pattren, also known as the delegate pattern, belongs to the structural design pattern, and its importance is self-evident. I believe that after reading this article, many design patterns will find the shadow of Proxy pattern. So what is the agency model? In fact, the agent is not uncommon in our daily life, for programmers the most common contact is the agent of the Internet, connect to the proxy server address, you can easily tour the world’s network; All in all, you may not notice, but agents are everywhere, in real life, and in our Code world! In this case, let’s explore how common the agency model is. Let’s first look at the definition of proxy mode.

define

Provide a proxy for other objects to control access to this object.

Usage scenarios

When it is difficult to access an object directly or not, it can be accessed indirectly through a proxy object. In order to ensure transparency of client use, the proxy object and the proxy object need to implement the same interface.

UML class diagrams

  • Subject: Abstract topic class; The main responsibility of this class is to declare the common interface methods of the real topic and the proxy, and this class can be either an abstract class or an interface.
  • RealSubject: RealSubject class; This class, also known as a delegated or proxyed class, defines the real objects represented by the proxy that execute the concrete business logic methods, while the client class indirectly invokes the methods defined in the real topic through the proxy class.
  • ProxySubject: proxy class; Also known as a delegate or proxy class, this class holds a reference to the real topic class and acts as a proxy by calling the corresponding interface method in the real topic class in the interface method it implements.
  • Client: The type of the Client class that uses the proxy class.

Code sample

The proxy mode can be roughly divided into two parts, one is static proxy, but dynamic proxy. In contrast to static proxies, which have only concrete proxy objects, dynamic proxies generate proxy objects dynamically through reflection, meaning that we do not need to know who the proxy object is at code stage, and the proxy will be determined at execution stage. Let’s take a look

A simple example

Static agent

Business Background: When programmer X was working in the company, he met the situation that the company delayed his salary or even deducted his salary. In this case, programmer X still solved the problem through legal channels. At this time, he needed to hire a lawyer as his litigation agent

Litigation interface class:

public interface ILawsuit {

    /** * Submit the application */
    void submit(a);

    /**
     * 举行举证
     */
    void burden(a);

    /**
     * 开始辩护
     */
    void defend(a);

    /** * Litigation completed */
    void finish(a);
}
Copy the code

Specific Litigant (X programmer) :

public class XProgrammer implements ILawsuit {
    @Override
    public void submit(a) {
        System.out.println("Boss owes X programmer salary, file for arbitration!");

    }

    @Override
    public void burden(a) {
        System.out.println("Here's the contract and the bank payroll for the past year.");

    }

    @Override
    public void defend(a) {
        System.out.println("Proof! There is no need to say more!");

    }

    @Override
    public void finish(a) {
        System.out.println("Successful! Judgment boss from this day within 7 days settlement salary!"); }}Copy the code

Lawyer of X programmer (agent object) :

public class ProxyLawyer implements ILawsuit {
    /** * holds a reference to a specific proxy, in this case the X programmer, or any other Y programmer, just to be specific. * /
    private ILawsuit mLawsuit;

    public ProxyLawyer(ILawsuit lawsuit) {
        mLawsuit = lawsuit;
    }

    @Override
    public void submit(a) {
        mLawsuit.submit();
    }

    @Override
    public void burden(a) {
        mLawsuit.burden();
    }

    @Override
    public void defend(a) {
        mLawsuit.defend();
    }

    @Override
    public void finish(a) { mLawsuit.finish(); }}Copy the code

test:

    @Test
    public void testProxy(a){

        / / X programmers
        ILawsuit lawsuit = new XProgrammer();

        // The programmer hired a lawyer and left his affairs to the lawyer
        ILawsuit proxyLawyer = new ProxyLawyer(lawsuit);

        // The lawyer begins to process
        proxyLawyer.submit();
        proxyLawyer.burden();
        proxyLawyer.defend();
        proxyLawyer.finish();
    }
Copy the code

output:

Boss owes X programmer salary, apply for arbitration! This is the contract book and the bank salary flowing water of the past year is conclusive! There is no need to say more! Successful lawsuit! Sentence boss from now on7Settle wages within days!Copy the code

A dynamic proxy

Java provides us with a very convenient dynamic proxy interface InvocationHandler, which requires overriding its invoke method.

Let’s modify the above example slightly:

Dynamic proxy classes (here understood as lawyer objects)

public class DynamicProxy implements InvocationHandler {

    /** * references to the agent (here understood as X programmer) */
    private Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Call its proxy's method through reflection
        returnmethod.invoke(object,args); }}Copy the code

test:

    @Test
    public void testDynamicProxy(a){

        / / X programmers
        ILawsuit lawsuit = new XProgrammer();

        // Create a dynamic proxy object.
        DynamicProxy dynamicProxy = new DynamicProxy(lawsuit);

        // Get the ClassLoader from the agent
        ClassLoader classLoader = lawsuit.getClass().getClassLoader();

        // Dynamically construct a proxy lawyer out
        ILawsuit proxyLawyer = (ILawsuit) Proxy.newProxyInstance(classLoader, new Class[]{ILawsuit.class}, dynamicProxy);

        // The lawyer begins to process
        proxyLawyer.submit();
        proxyLawyer.burden();
        proxyLawyer.defend();
        proxyLawyer.finish();
    }
Copy the code

output:

Boss owes X programmer salary, apply for arbitration! This is the contract book and the bank salary flowing water of the past year is conclusive! There is no need to say more! Successful lawsuit! Sentence boss from now on7Settle wages within days!Copy the code

The running result is the same as that of the static proxy, so it can be seen that the dynamic proxy proxies N multiple proxy classes through a proxy class, its essence is to decouple the proxy and the proxy, so that there is no direct coupling relationship between the two. In contrast, static proxy can be used to proxy the implementation class under a given interface. If the interface is different, it needs to redefine different proxy classes, which is the most complicated, but static proxy is more in line with object-oriented principles. It is up to you to decide which way to implement the proxy at development time.

conclusion

The proxy pattern is widely used, and you can see the shadow of the proxy pattern in the later structural patterns, some patterns as a design pattern alone, rather than a targeted optimization of the proxy pattern. Moreover, the proxy pattern has few drawbacks. It is a pattern of fragmentation to a very small extent, and if there is one drawback, it is the common fault of design patterns, the increase in classes. But in this case, what’s wrong with even a small increase in classes, right?

Article code address

Special thanks to

Android source code design pattern analysis and combat

Thank you for reading, thank you!