当前位置:网站首页>Which is the best agency mode or decoration mode
Which is the best agency mode or decoration mode
2022-06-22 06:37:00 【Cappuccino Haichen】
Catalog
1、 Components and methods used in development
3.2、Subject Implementation class of interface RealSubject
3.3、InvocationHandler Implementation class of ,Cache Call processor
4、 increase InvocationHandler An implementation class SyCache
5、 Modify and supplement JDKProxyTest
1、 What problems can decoration pattern solve
2、 From class diagram to decoration pattern
2.1、Component Component interface
2.2、CorrectComponent Specific component implementation class
2.3、CorrectDecorator Specific decorators 1
2.4、CorrectDecorator2 Specific decorators 2
2.5、Condition Auxiliary condition class
2.6、DecoratorWrapper Decorator packaging class
Four 、 What's the difference between dynamic proxy and decoration mode
One 、 Preface
Design patterns , As a programmer, I still need to master some . As small as software intermediate designer exam 、 interview 、 Read the source code of the framework , Big to daily development 、 The system architecture will be encountered . And the author is also back in the period of College , I have a little knowledge of design patterns .
JDK A dynamic proxy , Its role in the world of source code is particularly important , Such as MyBatis Log module of 、binding Module etc. ,Spring Of AOP etc. . In daily development , You can also capture its shadow . An important goal of using proxies is to control access to the proxied classes , You can do some prefixes in the proxy class / Post processing , Such as : cache 、 journal 、 Business 、 jurisdiction wait . Use JDK The premise of dynamic proxy is : The proxied class must be an interface or its implementation class . If the proxy class is not an interface or an interface implementation class , And you want to use dynamic proxies , Consider using CGLIB、Javassist technology . This is a hard skill , well Java The engineer 、 The knowledge that architects must have .
Decoration mode , You can dynamically add functions to objects , This is a classic introduction . It may not be often encountered in daily development , But you can still capture it in the source code .
JDK In fact, there have always been many disputes between dynamic agent mode and decoration mode , Many scholars believe that there is no big difference between them , Even call them the same thing . Today, let's discuss their differences from an experimental point of view , As Grandpa Deng Xiaoping said :“ Practice is the only criterion for testing truth ”.
Two 、JDK Dynamic proxy model
Why are there so many proxy patterns , This is just one of them . Because in daily development , Common is to use JDK A dynamic proxy . Interested readers can study other types of agency models by themselves .
1、 Components and methods used in development
Development JDK The dynamic agent component is InvocationHandler Interface as well as Proxy class , Their responsibilities are as follows :
| class | Class |
| Proxy class | Responsible for generating proxy class And associated with Call processor (InvocationHandler Implementation class of interface ) |
| InvocationHandler Interface | Responsible for handling the logic of the agent , Such as : cache 、 journal 、 Business 、 jurisdiction wait |
1.1、 describe
Proxy The generated proxy class does not handle logic , Abstract and very real. You don't even see how to write logic in the proxy class body , But it will be delegated to Call processor Of invoke() Method processing logic , That's why there are more InvocationHandler Interface and its implementation class . We all know , To call a class's Non static methods , Generally, you have to go through it example To call methods . Easy to handle ,Proxy The generated proxy class does not handle logic , Which is delegated to the calling processor invoke() Method treatment , Then call the method that calls the processor , You must at least get an instance of it . so Proxy Of newProxyInstance() Method ( This method is often used in development ) You have to call the processor example Incoming . Let's take a look at the parameters of this method in the source code :
Source code :
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Method is responsible for creating proxy class instances , And the proxy class is associated with the calling processor that takes over processing the logical task .
loader: Class loader , Responsible for loading proxy classes .
interfaces: An array type , Indicates that an array of interface objects is provided , Then the proxy class implements all the methods of these interfaces and can call .
h:InvocationHandler Interface type , The proxy class will pass through InvocationHandler Implement an instance of a class to call invoke() Method processing logic .
2、 It's already said , The proxy class delegates to InvocationHandler Interface implementation classes to handle tasks , Task logic must go through invoke() Method , Let's see what it looks like in the source code :
/**
* Processes a method invocation on a proxy instance and returns
* the result. This method will be invoked on an invocation handler
* when a method is invoked on a proxy instance that it is
* associated with.
*
* @param proxy the proxy instance that the method was invoked on
*
* @param method the {@code Method} instance corresponding to
* the interface method invoked on the proxy instance. The declaring
* class of the {@code Method} object will be the interface that
* the method was declared in, which may be a superinterface of the
* proxy interface that the proxy class inherits the method through.
*
* @param args an array of objects containing the values of the
* arguments passed in the method invocation on the proxy instance,
* or {@code null} if interface method takes no arguments.
* Arguments of primitive types are wrapped in instances of the
* appropriate primitive wrapper class, such as
* {@code java.lang.Integer} or {@code java.lang.Boolean}.
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;Parameters to describe :
proxy: The proxied class .
method: Method of the class being proxied when called Method object .
args: Parameters of the method of the class being proxied when calling .
3、 experimental data
3.1、Subject Interface
public interface Subject {
String doSomething();
}3.2、Subject Implementation class of interface RealSubject
public class RealSubject implements Subject {
@Override
public String doSomething() {
System.out.println(" I'm real Object");
return " I am a RealSubject";
}
}3.3、InvocationHandler Implementation class of ,Cache Call processor
package com.ceam.designer.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Cache implements InvocationHandler {
/**
* The real class encapsulated here can generally be :Object type 、 Interface type 、Class type
*/
// private Object object;
//
// Cache(Object object) {
// this.object = object;
// }
private Subject object;
/**
* Initialize fields ,method.invoke(object, args) This field will be used in
*
* @param object Real object
*/
Cache(Subject object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----Before handler----");
// Call the method of the real object , Return value result
Object result = method.invoke(object, args);
System.out.println((String)result);
System.out.println("----After handler----");
// Return return value
return result;
}
}
3.4、 Test class
package com.ceam.designer.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class JDKProxyTest {
public static void main(String[] args) {
// Declare a parent class to create a child class
Subject subject = new RealSubject();
// Encapsulate real classes
InvocationHandler cache = new Cache(subject);
// Generate proxy instance , Associated call handler
/**
* About the first and second parameters of the input parameter , It's usually : The first is the class loader for the interface , The second is new Class[]{ Interface Class}
*/
Subject proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class}, cache);
String result = proxy.doSomething();
System.out.println(" Return results :" + result);
System.out.println("***********************************");
Subject proxy2 = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
subject.getClass().getInterfaces(), cache);
proxy2.doSomething();
}
}3.5、 Console print results :

4、 increase InvocationHandler An implementation class SyCache
package com.ceam.designer.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class SyCache implements InvocationHandler {
/**
* The real class encapsulated here can generally be :Object type 、 Interface type 、Class type
*/
// private Object object;
//
// Cache(Object object) {
// this.object = object;
// }
private Subject object;
/**
* Initialize fields ,method.invoke(object, args) This field will be used in
*
* @param object Real object
*/
SyCache(Subject object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----SyCache Before handler----");
// Call the method of the real object , Return value result
Object result = method.invoke(object, args);
System.out.println((String)result);
System.out.println("----SyCache After handler----");
// Return return value
return result;
}
}5、 Modify and supplement JDKProxyTest
package com.ceam.designer.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class JDKProxyTest {
public static void main(String[] args) {
// Declare a parent class to create a child class
Subject subject = new RealSubject();
// Encapsulate real classes
InvocationHandler cache = new Cache(subject);
// Generate proxy instance , Associated call handler
/**
* About the first and second parameters of the input parameter , It's usually : The first is the class loader for the interface , The second is new Class[]{ Interface Class}
*/
Subject proxy = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class}, cache);
String result = proxy.doSomething();
System.out.println(" Return results :" + result);
System.out.println("***********************************");
Subject proxy2 = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
subject.getClass().getInterfaces(), cache);
// Encapsulate real classes
InvocationHandler syCache = new SyCache(subject);
proxy2 = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
subject.getClass().getInterfaces(), syCache);
proxy2.doSomething();
}
}Print the results :

6、 summary
No matter from idea The code in , Or the printed results can be seen : Use JDK A dynamic proxy , You can't make a few InvocationHandler The implementation classes of the interface are freely composed , Only one of them can be used to provide services for proxy classes .
3、 ... and 、 Decoration mode
1、 What problems can decoration pattern solve
In practical production , New demands are always emerging . When there is a new need , It is necessary to add new functions to some components to meet these requirements . We can directly modify the existing component code and add new functions , This will obviously destroy the existing components stability , After modification , The entire assembly needs to be retested , Can be used online . This is a clear violation of “ to open up - closed ” principle .
Decoration mode Can help us solve the above problems , Decoration mode can dynamically add functions to objects , It is based on combination Functional . In actual development , In the industry, it is recommended to use combination to expand the functions of the system , Less inheritance . Please remember one sentence : Combination over inheritance .
2、 From class diagram to decoration pattern

chart 2-1
Component( Components ): The component interface defines the behavior of all component implementation classes and all decorators .
CorrectComponent( Specific component implementation class ): The specific component implementation class implements Component( Components ) Interface .
Decorator( Decorator ): Parent of all decorators , It is an implementation of Component Abstract class of interface , And encapsulated a Component object , That is, the object to be decorated . And the object to be decorated as long as Component The type is enough , This realizes the combination and reuse of decorators . But it doesn't have to happen , Some designs can also omit it , And directly use the specific decorator , We have to be flexible .
CorrectDecorator( Specific ornaments ): Concrete decorator implementation classes , It will add some functions to the decorator , That is, the newly added requirement function is implemented in this implementation class . Of course, there can be more than one decorator , And they are all independent of each other .
The following class diagrams are some of my own research and design class diagrams , The main part is the above class diagram structure

chart 2-2
DecoratorWrapper From the picture 2-2 We can see that , It is responsible for creating decorators , See the following for the specific code 2.6.
2.1、Component Component interface
package com.ceam.designer.decorator.two;
/**
* Component.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public interface Component {
void doSomething();
}2.2、CorrectComponent Specific component implementation class
package com.ceam.designer.decorator.two;
/**
* CorrectComponent.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class CorrectComponent implements Component {
@Override
public void doSomething() {
System.out.println(" I am a specific component ");
}
}2.3、CorrectDecorator Specific decorators 1
package com.ceam.designer.decorator.two;
/**
* CorrectDecorator.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class CorrectDecorator implements Component {
private final Component component;
CorrectDecorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
component.doSomething();
this.enchange();
}
private void enchange() {
System.out.println(" The rear enhancement ");
}
}2.4、CorrectDecorator2 Specific decorators 2
package com.ceam.designer.decorator.two;
/**
* CorrectDecorator2.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class CorrectDecorator2 implements Component {
private final Component component;
CorrectDecorator2(Component component) {
this.component = component;
}
@Override
public void doSomething() {
component.doSomething();
this.enchange();
}
private void enchange() {
System.out.println(" The rear enhancement 2");
}
}
2.5、Condition Auxiliary condition class
package com.ceam.designer.decorator.two;
/**
* Condition.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class Condition {
public static Boolean d1;
public static Boolean d2;
public Condition d1(boolean d1) {
this.d1 = d1;
return this;
}
public Condition d2(boolean d2) {
this.d2 = d2;
return this;
}
}2.6、DecoratorWrapper Decorator packaging class
package com.ceam.designer.decorator.two;
/**
* DecoratorWrapper.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class DecoratorWrapper implements Component{
private static Condition condition;
public static Boolean d1;
public static Boolean d2;
DecoratorWrapper() {
}
DecoratorWrapper(Condition condition) {
this.condition = condition;
}
@Override
public void doSomething() {
this.en();
}
private void en() {
Component component = new CorrectComponent();
if (Condition.d1) {
component = new CorrectDecorator(component);
}
if (Condition.d2) {
component = new CorrectDecorator2(component);
}
component.doSomething();
}
public DecoratorWrapper d1(boolean d1) {
this.d1 = d1;
return this;
}
public DecoratorWrapper d2(boolean d2) {
this.d2 = d2;
return this;
}
}2.7、 Test class
package com.ceam.designer.decorator.two;
/**
* Test.java
* <p>
* Copyright
* All Rights Reserved.
* Project: test-center
* Description:
*
* @author : Administrator
* History:
* 2021-09-04 created by Administrator
*/
public class Test {
public static void main(String[] args) {
// Component component = new CorrectComponent();
// component = new CorrectDecorator(component);
// component = new CorrectDecorator2(component);
// component.doSomething();
Component component1 = new DecoratorWrapper(new Condition()
.d1(false)
.d2(false));
component1.doSomething();
System.out.println("2----------------------------------------");
Component component2 = new DecoratorWrapper(new Condition()
.d1(true)
.d2(false));
component2.doSomething();
System.out.println("3----------------------------------------");
Component component3 = new DecoratorWrapper(new Condition()
.d1(true)
.d2(true));
component3.doSomething();
System.out.println("4----------------------------------------");
Component component4 = new DecoratorWrapper().d1(true).d2(true);
component4.doSomething();
}
}
2.8、 test result
2.9、 summary
It can be seen from the experimental results that : Decorative patterns can be dynamically combined , Add functions to the decorated objects .
Four 、 What's the difference between dynamic proxy and decoration mode
What's the difference between dynamic proxy and decoration mode , I will not say more , Everything is in the experimental data , Please study carefully . After all, the author has made a lot of efforts , From the source code knowledge , After the experiment, the conclusion is , It has been summarized to the readers . If you have any questions, please leave a message , I try my best to answer .
边栏推荐
- [NAND file system] UBI introduction
- Pytest数据参数化&数据驱动
- [5g NR] mobile phone ID number IMEI and imeisv
- The tidb community offline exchange meeting was seen by the partners from Tianjin and Shijiazhuang~
- 入门级测试Kotlin实现PopWindow弹窗代码
- Expert system clips from introduction to mastery (I) introduction and overview of clips
- SQL 注入漏洞(十一)宽字节注入
- 【M32】单片机 svn 设置忽略文件
- MySQL Niuke brush questions
- Py之scorecardpy:scorecardpy的简介、安装、使用方法之详细攻略
猜你喜欢

ReadWriteLock

SQL injection vulnerability (XIV) XFF injection attack

SQL injection vulnerability (x) secondary injection

【Rust 日报】2022-01-23 WebAPI Benchmarking

Expert system clips from introduction to mastery (I) introduction and overview of clips

Single cell literature learning (Part3) -- dstg: deconvoluting spatial transcription data through graph based AI

5G终端标识SUPI,SUCI及IMSI解析

Surfer grid file clipping

Seven parameters of thread pool and custom thread pool
![[5g NR] ng setup of ngap protocol](/img/aa/bbe4b345374d2cf2ab3bfde5e94d7c.png)
[5g NR] ng setup of ngap protocol
随机推荐
BlockingQueue four sets of APIs
Error encountered while importing keras typeerror: descriptors cannot not be created directly If this call came from a _
[PHP]TP6 CLI模式下创建tp6和多应用配置以及常见问题
SQL 注入漏洞(十一)宽字节注入
Event preview edgex developer summit @ Nanjing station is coming!
[5g NR] ng setup of ngap protocol
[write CPU by yourself] implementation of exception related instructions
Py之Optbinning:Optbinning的简介、安装、使用方法之详细攻略
Common auxiliary classes - (key)
New GDI functions and functions introduced in MiniGUl version 1.1.0 (II)
[M32] simple interpretation of MCU code, RO data, RW data and Zi data
Pytest data parameterization & data driven
DL and alignment of spatially resolved single cell transcriptomes with Tangram
性能对比分析
博客添加邮箱私信 快捷
Test ofnatural clusters via s-dbscan a self tuning version of DBSCAN
《数据安全实践指南》- 数据采集安全管理
关于solidity的delegatecall的坑
SQL injection vulnerability (x) secondary injection
5g-guti detailed explanation