概论
什么是代理模式呢?代理模式是这么定义的:为其他对象提供一种代理以控制对这个对象的访问。
代理模式示例
代理模式中有三种角色,分别是抽象主题角色,具体主题角色和代理主题角色。
1.抽象主题角色指的是抽象的行为,往往使用接口或者抽象类来表达。或者使用接口和抽象类混合使用。
2.具体主题角色指的是具体的行为,该行为是抽象行为的具体化,也是抽象行为的具体表达,即抽象行为的实现类或者子类。
3.代理主题角色指的是代理具体行为的一种角色,它的存在就是代替具体对象,并且灵活控制具体对象的表达。
我们以网上购物为例。首先我们需要有一个购物消费者接口,用来定义购物的行为:
1.账号登录。
2.生成订单。
3.订单支付。
1 public interface IConsumer { 2 3 public void login(String name, String password); 4 5 public void order(String goodsName); 6 7 public void pay(); 8 9 }
再来新增一个具体的消费者。具体的行为。
1 public class RealConsumer implements IConsumer { 2 @Override 3 public void login(String name, String password) { 4 System.out.println("["+name+"]登陆成功"); 5 } 6 7 @Override 8 public void order(String goodsName) { 9 10 System.out.println("["+goodsName+"]生成订单成功"); 11 12 } 13 14 @Override 15 public void pay() { 16 17 System.out.println("订单支付成功"); 18 19 } 20 }
我们再来定义一个场景类Client:
1 public class Client { 2 3 public static void main(String[] args) { 4 5 IConsumer consumer = new RealConsumer(); 6 7 consumer.login("抒尽", "123456"); 8 consumer.order(); 9 consumer.pay(); 10 11 } 12 }
场景类中直接创建真实的消费者,这个消费者再进行购物的一系列的动作。那么问题来了,天天自己买东西太累了,找个人来代理购物这个行为。于是我们需要增加一个代理的角色,我们把它叫作代理类。
1 public class ProxyConsumer implements IConsumer { 2 3 private IConsumer consumer = null; 4 5 public ProxyConsumer(IConsumer consumer) { 6 this.consumer = consumer; 7 } 8 9 @Override 10 public void login(String name, String password) { 11 consumer.login(name, password); 12 } 13 14 @Override 15 public void order() { 16 consumer.order(); 17 18 } 19 20 @Override 21 public void pay() { 22 consumer.pay(); 23 } 24 }
第1行:代理消费者依然是消费接口的实现类。
第3行:代理消费者持有真实消费者的引用。
第5行-7行,真实消费者是在场景类中以参数形式传递给代理消费者。
第11行,16行,22行:使用真实消费者对象参与购物的所有动作。
最后我们再来修改一下场景类。
public class Client { public static void main(String[] args) { IConsumer realConsumer = new RealConsumer(); IConsumer proxyCosumer = new ProxyConsumer(realConsumer); proxyCosumer.login("抒尽", "123456"); proxyCosumer.order(); proxyCosumer.pay(); } }
运行结果如下所示:
[抒尽]登陆成功
生成订单成功
订单支付成功
OK,执行的结果没有任何变化,本来是自己要去做的动作,结果可以找代理来做,这就是代理模式。代理模式最大的特点就是把控了真实对象的定位,例如我们需要打印生成订单的时间,统计生成订单到支付成功的时间。支付之后,增加业务接口回调。如果在真实接口中,除了扩展代码之后别无其他任何选择,这就违背的开闭的原则。不变的部分和变化的部分需要分离。
代理模式的优点和使用场景
1.职责清晰。真实的角色实现真实的业务逻辑。其他逻辑,比如打印时间,日志处理,事务处理就交给了代理角色。
2.高扩展性。代理对象会跟着真实对象的变化而变化,真实对象业务发生了变化,代理对象不需要修改任何东西,跟着发生变化。
3.智能化。尤其是接下来要介绍的spring中aop采用的动态代理。这个特性把智能化的特点表现的淋漓尽致。
使用场景:在spring源代码aop部分非常巧妙使用了动态代理。
代理模式的分类
代理模式分为三类:普通代理,强制代理,动态代理。
什么是普通代理呢?要求场景类只能访问代理角色,而不能直接访问真实角色,在上面的例子中,我们不能够在场景类中直接去产生一个realConsumer对象了。
什么是强制代理呢?强制代理和普通代理刚好相反。必须要通过真实角色找到代理角色。
什么是动态代理呢?动态代理在实现阶段,即代码阶段不需要关心谁代理谁,而是在运行阶段才去确定代理类。
既然有动态代理,那必然有静态代理,静态代理指的是手工去构建代理类,因此静态代理包括了普通代理和强制代理。