代理设计模式
Posted hymKing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理设计模式相关的知识,希望对你有一定的参考价值。
今天在看Spring Aop,Aop在设计上使用的动态代理的设计模式,因此来对代理设计模式做一个系统性的复习总结,思考代理设计模式在实际架构工作中,以及业务代码的设计中所可能的实际应用场景。
首先,代理设计模式是一种结构型设计模式。代理设计模式是一种使用率非常高的设计模式,其定义是为其它对象提供一种代理以控制这个对象的访问。这个“控制”指对原有对象中的方法控制,既可以是增强,也可以是限制。
联想一下,我们在实际生活中的一个代理场景,租房经纪人,租房经纪人是对实际房东的代理,经纪人操作着房东房子的租用权利;对于房东,房东是委托租房经纪人去向外租出自己的房子。其实代理模式也叫做委托模式。很显然,在这个实际场景中,存在核心的两方角色:代理方、委托方,故也被叫做委托模式,是从委托方角色定义的。另外实现委托的方式,除了代理还有别的方式。所以,通常情况下,我们仍然更多称这种“通过为其它对象提供一种代理对象来控制某个对象的访问”的这种代码结构设计方式,为代理设计模式。
一、代理设计模式的通用模型
通过类图看一下代理设计模式中的三个角色的定义:
**Subject抽象主题角色(接口):**抽象主题角色可以是抽象类,也可以是接口,是一个普通的业务类型的定义,无特殊要求。
**RealSubject具体主题角色(实现类):**被委托角色、被代理角色,是业务逻辑的具体执行者。
**Proxy代理主题角色:**代理类,负责对真实角色的应用,把所有抽象主题类定义的方法(request())限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理工作和善后处理工作。
下面看一下具体的通用模型的代码实现:
Subject.java
package com.design.proxymode.common;
/**
* 抽象主题角色
*/
public interface Subject {
public void request();
}
RealSubject.java
package com.design.proxymode.common;
public class RealSubject implements Subject {
@Override
public void request() {
//业务逻辑处理
}
}
Proxy.java
package com.design.proxymode.common;
public class Proxy implements Subject {
//要代理的那个实现类
private Subject subject=null;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
before();
subject.request();
after();
}
//预处理
private void before() {
}
//善后处理
private void after() {
}
}
小结:
1、在上述代码中,可以看到Proxy具体代理谁,即被代理对象是通过构造函数传入的,在实际业务中,就由实际的场景模块来决策要创建谁的代理。这样的形式,一个代理类可以代理多个委托者或被代理者。
2、在Proxy的类中,有两个方法,分别为预处理before()和后处理after(),在真实角色subject.request()的执行前后,我们可以加入原有真实角色不具备的处理逻辑。Spring Aop框架也正是在解决before和after的优雅实现。
二、代理设计模式的应用
代理设计模式优缺点
代理设计模式优点:
-
职责清晰
真实角色只处理他核心关心的业务逻辑的处理
-
高扩展性
具体真实角色无论如何变化,只要实现了相同接口,代理类可以不需要做任何修改的情况下使用。
-
智能化
主要表现在动态代理设计上【后补】
关于代理模式的缺点,在后文中的会综合分析。
代理设计模式的分类
静态代理:
我们需要手动去创建代理对象的这种方式,被称为静态代理。在静态代理模式中,又可以细分为一下两种情况,分别为普通代理、强制代理。
普通代理:普通代理要求客户端只能访问代理角色。类图如下:
强制代理:一般思维是通过代理找到真实角色,但是强制代理,却是要通过真实角色找到代理角色,而且是强制性的必须的。类图如下:
普通代理的应用场景很容易理解,强制代理的应用场景,举一个现实世界中的例子,企业内部的审批系统,一般领导可以在特定情况下,指定代理审批人,而且只要领导自己有权限指定。是不是实现这样的一个审批功能,就可以应用我们的强制代理模式。
关于静态代理和普通代理的代码,就不贴出来了,核心是对这两种代理应用场景的思考和理解。
三、动态代理
动态代理是通过java jdk的Proxy类创建指定接口的代理对象,而这个对象的创建过程是在运行期间,动态代理实际上是JVM在运行期动态创建class字节码并加载的过程。
很显然这样一套可实现动态代理技术,会给我们的编码工作带来很大的便捷。先看一下动态代理的基本实现:
代码如下:
Subject.java
package com.design.proxymode.dynamic;
/**
* 抽象主题
*/
public interface Subject {
//业务操作
public void doSomething();
}
RealSubject.java
package com.design.proxymode.dynamic;
/**
* 真实主题
*/
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("do something...");
}
}
MyInvocationHandler.java
package com.design.proxymode.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理的代用处理器
*/
public class MyInvocationHandler implements InvocationHandler {
//被代理的对象
private Object target=null;
//通过构造函数传入一个对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理方法
return method.invoke(this.target,args);
}
}
DynamicProxy.java
package com.design.proxymode.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxy<T> {
public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler){
//正常返回代理对象
return (T) Proxy.newProxyInstance(loader, interfaces, handler);
}
}
Client.java
package com.design.proxymode.dynamic;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
//定义一个主题角色
Subject realSubject = new RealSubject();
//定义一个处理者handler,其实就是方法的触发器
MyInvocationHandler handler = new MyInvocationHandler(realSubject);
//定义一个代理主题角色,主题角色、代理角色都是用上转型的方式定义
Subject proxy= DynamicProxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),handler);
//代理执行行为
proxy.doSomething();
}
}
通过类图和代码实现可以发现,代理角色不用再和真实角色实现相同的接口了,而是通过DynamicProxy传入的参数动态的生成相应接口实现类的代理类,这样的技术是不是很便捷。
InvocationHandler是jdk提供的动态代理接口,对被代理类的方法进行代理。
至此,关于代理的基础技术点就完事了,接下来会思考:动态代理能给我我们带来怎样的应用的好处呢,回顾文章开始所说的Aop技术,正是对动态代理的典型应用。
以上是关于代理设计模式的主要内容,如果未能解决你的问题,请参考以下文章