设计模式之代理模式
定义
为其他对象提供一种代理,以控制对这个对象的访问。在一些情况下,一个对象不适合或者不能直接引用另一对象,而代理对象可以在客户端和目标对象之间起到中介的作用
角色的分类
(1)抽象角色
定义代理角色和真实角色的公共对外接口
(2)真实角色
实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色的调用。
(3)代理角色
代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
类图如下:
代理分类
(1)静态代理(静态定义代理类)
(2)动态代理(动态生成代理类)
-JDK自带的动态代理
-javaassist字节码操作库实现
-CGLIB
-ASM(底层使用指令,可维护性较差)
静态代理
静态代理也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
例子:歌手和经纪人
代码如下:
抽象角色:定义代理角色和真实角色的公共对外接口
/**
* 抽象角色
* @author mama
*
*/
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
真实角色:
/**
* 真实角色
* @author mama
*
*/
public class RealStar implements Star{
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
}
}
代理角色:
/**
* 代理角色
* @author mama
*
*/
public class ProxyStar implements Star {
/**
* 注入真实角色实现的对外接口
*/
private Star star;
public ProxyStar(Star star) {
super();
this.star = star;
}
@Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("ProxyStar.confer()");
}
@Override
public void signContract() {
System.out.println("ProxyStar.signContract()");
}
@Override
public void sing() {
star.sing();
}
}
测试(客户端)
public class Client {
public static void main(String[] args) {
Star star=new RealStar();
ProxyStar proxy=new ProxyStar(star);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
类图:
动态代理
动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件。代理角色和真实角色的联系在程序运行时确定。
代码如下
抽象角色:定义代理角色和真实角色的公共对外接口
/**
* 抽象角色
* @author mama
*
*/
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
真实角色:
/**
* 真实角色
* @author mama
*
*/
public class RealStar implements Star{
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void sing() {
System.out.println("RealStar(周杰伦本人).sing()");
}
}
代理角色处理器:
/**
* 代理角色处理器
* @author mama
*
*/
public class StarHandler implements InvocationHandler{
/**
* 注入真实角色的对外接口
*/
private Star star;
public StarHandler(Star star) {
super();
this.star = star;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
System.out.println("真正的方法执行前!");
System.out.println("面谈,签合同,预付款,订机票");
if(method.getName().equals("sing")) {
object=method.invoke(star, args);
}
System.out.println("真正的方法执行后!");
System.out.println("收尾款");
return object;
}
}
测试(客户端)
和静态代理不同
public class Client {
public static void main(String[] args) {
Star star=new RealStar();
StarHandler handler=new StarHandler(star);
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler);
proxy.sing();
}
}
动态代理相比于静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
优点:
业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
缺点:
由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。
应用场景:
(1)安全代理:屏蔽对真实角色的直接访问
(2)远程代理:通过代理类处理远程方法调用(RMI)
(3)延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象等。
开发框架中的应用场景:
(1)Struts2中拦截器的实现
(2)数据库连接池关闭处理
(3)Hibernate中延迟加载的实现
(4)Mybatis中实现拦截器插件
(5)AspectJ的实现
(6)Spring中AOP的实现
-日志拦截
-声明式事物处理
(7)web service
(8)RMI远程方法调用
。。。。。。。。。