This is the 12th day of my participation in the More text Challenge. For details, see more text Challenge

Wechat official account: Xiao Lei

When efforts to a certain extent, luck from with you accidentally meet.

preface

The five creator modes are covered. Today we begin to study the structural mode.

So what is a structural pattern? This is not the same as the purpose of the creation schema, as our data structure is divided into linear tables, linked lists, stacks, trees, graphs, and so on. It’s more about processing different data through a series of structures of its own. The same is true of structural patterns, which describe how classes or objects are grouped into larger structures in a certain layout.

It is divided into class structure pattern and object structure pattern.

  • The class inheritance structure organizes interfaces and classes only through inheritance
  • And the object structure can be combined into multiple objects, more flexible

There are seven types of structural models:

  • The proxy pattern
  • Adapter mode
  • Decorator mode
  • The bridge model
  • The appearance model
  • Portfolio model
  • The flyweight pattern

First, get started with the agent mode

1.1 What is the Agent Mode?

Proxy Patten is a common design pattern

A proxy is a class that can act as an interface to something else. An agent can be an interface to anything: a network connection, a large object in storage, a file, or other resource that is expensive or impossible to copy.

In short, agent B implements A’s function, assigns the function to A, and adds its own function.

For example, a matchmaker who introduces a man to a woman is only a matchmaker, and the subsequent success depends on the two men and women. At the same time, she adds her own function: to charge some fees.

1.2 Why does the agent mode occur?

Still starting from the above example, in our life, we really need a lot of such “agency” roles, just like the intermediary role of matchmaker, intermediary, broker and so on. The reason why they appear is obvious, because there is such a need. Most of the time, we cannot directly find the other half, or directly find the house. Through a matchmaker’s introduction, she will do something “fancy” to bring you together.

In summary, we use proxy objects instead of accessing real objects, so that we can extend the functionality of the target object by providing additional operations without modifying the original target object. That’s where the proxy model comes in, extending the functionality of the target, turning a spiritual guy into a “man of god.”

1.3 Usage Scenarios?

  • Remote agent

    The local service requests the remote service over the network. In order to achieve local to remote communication, we need to implement network communication, which may handle exceptions. For good code design and maintainability, we hide the network communication part and expose only an interface to the local service through which to access the functionality provided by the remote service without worrying too much about the details of the communication part.

  • Firewall agent

    When you configure your browser to use proxy, the firewall redirects your browser requests to the Internet; When the Internet returns a response, the proxy server forwards it to your browser.

  • Protect or Access agent

    Control access to an object by giving different levels of access to different users if needed.

There are many application scenarios for the proxy pattern, although it adds to the complexity of the system to some extent.

However, it has several advantages:

  • The proxy pattern acts as a mediator between the accessing object and the target object
  • The proxy pattern extends the functionality of the target object
  • The proxy pattern divides the visitor and the target object, reducing the coupling degree of the system to some extent.

2. Java proxy mode

2.1 classification

As you can see from the above example, a proxy object acts as a mediator between the target object and the accessing object. In Java, it can be divided into static and dynamic proxies according to the generation time of the proxy class.

  • Static proxy: generated in the compiler
  • Dynamic proxy: Generated dynamically at the Java runtime
    • The JDK agent
    • Additional agent

2.2 the role

The proxy mode is divided into three roles:

  • Abstract roles: Business methods that declare real topics and proxy implementations through interfaces or abstract classes.
  • Real role: Implements the concrete business in the abstract role. It is the real object represented by the proxy object and the object to be referenced at the end.
  • Agent role: Provides the same interface as the real role. It contains internal references to the real role and can enhance the real role methods.

2.3 Static Proxy

Here we implement the above example with a static proxy.

Corresponding to the above case.

  • Methods in abstract roles can be defined as “find objects.
  • Object finding is implemented in the real role. For example, to define their own personality, mate criteria
  • The agent role implements, extends, embellishes, and charges the methods in the real role.

The code is as follows:

Public interface FindFriend {void FindFriend (); public interface FindFriend {void FindFriend (); } // 2, real object, Public class boy implements FindFriend{@override public void FindFriend () {system.out.println (" Can you make a boy? "); ); } // 3. public class ProxyMatchmaker implements FindFriend{ private Boy boy =new Boy(); @override public void findBoyFriend() {system.out.println (" Override public void findBoyFriend() ") {system.out.println (" Override public void findBoyFriend() ") {system.out.println (" Override public void findBoyFriend() ") {system.out.println (" Override public void findBoyFriend() "); ); boy.findBoyFriend(); "Boy, charge you $500! When it's done, I'll charge you 500, heh heh ~"); }} // 4. Public class Staticxytest {public static void main(String[] args) {ProxyMatchmaker = new ProxyMatchmaker(); proxyMatchmaker.findBoyFriend(); }}Copy the code

Output results:

Young man mind spirit will talk, will live potential, thief spirit! Can I be your boyfriend? $500 for you, young man! After the thing is done, charge you 500 again, hey hey ~Copy the code

Static proxy features:

  • The proxy class is implemented manually by creating a Java class that represents the proxy class
  • Also, the target class you want to proxy is defined

The downside is that access classes and target classes have increased, hundreds of boys and girls have been found, and many implementation classes and proxy classes have been affected.

2.4 JDK dynamic proxy

The JDK provides a standard solution to the pitfalls of static proxies, called dynamic proxies. Java provides a dynamic Proxy class, Proxy, which provides a static method to create Proxy objects to obtain Proxy objects.

Public interface FindFriend {void FindFriend (); public interface FindFriend {void FindFriend (); } // 2, real object, Public class BoyZ implements FindFriend{@override public void FindFriend () { System.out.println(" Can Sam be your boyfriend? ") ); } // 3, what did the matchmaker say? public class ProxyFactory { private BoyZ boyZ =new BoyZ(); Public FindFriend getProxyObject(){// GetProxyInstance (){// GetProxyInstance (){ Class loaders, used to load proxy classes, use real object Class loaders to Class<? >[] interfaces: Real objects and proxy objects implement the same interface InvocationHandler h: */ FindFriend o = (FindFriend) proxy.newProxyInstance (boyz.getClass ().getClassLoader(), Boyz.getclass ().getInterfaces(), new InvocationHandler() {/* Method instance args corresponding to the interface Method called on the proxy object: */ @Override public Object invoke(Object proxy, Method Method, Object[] args) throws Throwable {system.out. println(" Throwable, Throwable, Throwable, Throwable, Throwable, Throwable, Throwable, Throwable, Throwable, Throwable, Throwable ") ); Object result = method.invoke(boyZ, args); "Boy, charge you $500! When it's done, I'll charge you 500, heh heh ~"); return result; }}); return o; Public class staticxytest {public static void main(String[] args) {ProxyFactory = new ProxyFactory(); FindFriend proxyObject = proxyFactory.getProxyObject(); proxyObject.findBoyFriend(); }}Copy the code

Print result:

Young man mind spirit will talk, will live potential, thief spirit! Can John be your boyfriend? $500 for you, young man! After the thing is done, charge you 500 again, hey hey ~Copy the code

ProxyFactory: ProxyFactory: ProxyFactory: ProxyFactory: ProxyFactory: ProxyFactory

No, it’s a class that helps us find our proxy class. True proxy classes are those that are generated in memory while the program is running. Which is generated in the getProxyObject () method.

View the structure of the agent class using the Java diagnostic tool (Arthas) :

public final class $Proxy0 extends Proxy implements FindFriend { private static Method m3; public $Proxy0(InvocationHandler invocationHandler) { super(invocationHandler); } public final void findBoyFriend() { this.h.invoke(this, m3, null); } static { m3 = Class.forName("patten.proxy.FindFriend").getMethod("findBoyFriend", new Class[0]); return; } public class Proxy implements java.io.Serializable {protected InvocationHandler h; protected Proxy(InvocationHandler h) { this.h = h; }}Copy the code

This means that the actual Proxy class is a subclass of Proxy and inherits the methods of the abstract role, which also conforms to our previous definition of the Proxy role. By passing in the real role method, find the agent role method, polymorphic output.

The agent class role’s findBoyFriend () method then calls the InvocationHandler’s Invoke method. Shell () methods that actually implement real objects through reflection.

2.5 CGLibg dynamic proxy

In the above definition, if there is no interface for finding objects, only a straight boy is defined. In this case, the JDK dynamic proxy is not available because the JDK dynamic proxy requires you to define and proxy the interface.

CGLib is a powerful, high-performance code generation package. It provides proxies for classes that do not implement interfaces, a nice complement to the JDK’s dynamic proxies.

First, introduce the JAR package:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>
Copy the code

The code is as follows:

Public class BoyZ {public void boyfriend () {system.out.println (" Can I be your boyfriend? "); ); } // 2, Public class ProxyFactory implements MethodInterceptor {private BoyZ BoyZ =new BoyZ(); private BoyZ BoyZ =new BoyZ(); public BoyZ getProxyObject(){ //1. Tool class Enhancer Enhancer = new Enhancer(); //2. Set enhancer.setSuperClass (boyz.getClass ()); //3. Set enhancer.setCallback(this); BoyZ obj=(BoyZ obj)enhancer.create(); return obj; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy MethodProxy) throws Throwable {system.out.println (" boy mind spirit \n" + "boy mind spirit \n" +" boy mind spirit \n" + "boy mind spirit \n" + ); BoyZ o1 = (BoyZ) methodProxy.invokeSuper(o, objects); return o1; Public class Test {public static void main(String[] args) {ProxyFactory ProxyFactory = new ProxyFactory();  BoyZ proxyObject = proxyFactory.getProxyObject(); proxyObject.findBoyFriend(); }}Copy the code

The GGLib handles the class implementation by subclassing the target class and then overwriting the methods in it. Therefore, the target class cannot be final, and methods cannot be static/final.

2.6 Comparison of the three modes

2.6.1 JDK agent and CGLIB agent
  • Using CGLib to achieve dynamic proxy, CGLib bottom using ASM bytecode generation framework, using bytecode technology to generate proxy class, before JDK1.6 than using Java reflection efficiency. The only thing to note is that CGLib cannot proxy classes or methods that are declared final, because CGLib dynamically generates subclasses of the proxied class.

  • After JDK1.6, JDK1.7, and JDK1.8 gradually optimize the JDK dynamic proxy, the JDK agent efficiency is higher than CGLib agent efficiency when the number of calls is small. Only when a large number of calls are made, JDK1.6 and JDK1.7 are less efficient than CGLib agent efficiency. However, when JDK1.8 is used, JDK agents are more efficient than CGLib agents. So if you have interfaces that use JDK dynamic proxies, if you don’t have interfaces that use CGLIB proxies.

2.6.2 Dynamic proxy and Static Proxy
  • The main advantage of dynamic proxies over static proxies is that all methods declared in the interface are transferred to a single set of methods in the call handler (invocationHandler.Invoke). In this way, we can be flexible when the number of interface methods is large, rather than needing to relay each method like a static proxy.

  • If an interface adds a method, the static proxy pattern requires all proxy classes to implement the method in addition to all implementation classes. Increased code maintenance complexity. Dynamic proxies do not have this problem

Third, summary

This article has given you a primer on the proxy pattern, and while there are few scenarios where the proxy pattern is applied in real development, its ideas are deeply embedded in the source code of many frameworks, such as CGLIb and Spring AOP. That’s the idea of the agency model. This is the beginning of the structural pattern. The following will continue our brief tour of design mode, creation is not easy, might as well point a like and attention.