Proxy Pattern代理模式,可以说其是最简单易懂的一种结构型设计模式
模式思想
代理模式,其实大家不论是在日常生活还是软件开发领域见的都是比较多的。典型地,我们买商品一般不会直接去工厂去买,而是和商店这个中间商来打交道的。而这其实就体现了代理模式的精神内涵,即当client由于某种原因(存在困难、麻烦等原因)不便于直接使用某个对象时,可以通过使用代理者来间接的使用、访问某个对象。这样做的好处,一方面可以方便client使用,另一方面可以通过代理者可以增强对象原有的功能、行为,即所谓的AOP。该模式涉及到的角色也很少
- 抽象角色 : 为了保证代理对象与真实角色接口统一,故需一个抽象角色。用于定义共有的方法。即本文例子中的Sell接口
- 真实角色(即被代理角色) : 其即是被代理的角色。由于其才是真正执行相关操作的,故又被称作真实角色。即本文例子中的Apple类
- 代理角色 : 其是对真实角色的代理,通过内部持有真实角色实例进行请求转发,完成真正的行为调用。还可以根据实际需要(比如日志、安全、缓存等需求)来拓展、增强真实角色的行为。即本文例子中的AppleStore类
实现
现在,我们使用Java实现该模式来帮助人民群众更好的理解。首先定义一个抽象角色,即卖数码产品的Sell接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public interface Sell {
void sellPhone();
void sellPc(); }
|
现在,我们有一个被代理对象苹果公司Apple类,其可以从工厂直接出售产品
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public class Apple implements Sell {
@Override public void sellPhone() { System.out.println("Apple: Sell iPhone SE"); }
@Override public void sellPc() { System.out.println("Apple: Sell MacBook Pro"); } }
|
现在,我们为了方便人民群众购买苹果设备,提供了一个代理者——苹果经销商AppleStore类。可以看到其内部持有了Apple实例进行请求转发。与此同时,通过代理者实现了对原有功能的增强(makeAd、record方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
public class AppleStore implements Sell{
private Apple apple;
public AppleStore(Apple apple) { this.apple = apple; }
@Override public void sellPhone() { makeAd(); apple.sellPhone(); record(); }
@Override public void sellPc() { makeAd(); apple.sellPc(); record(); }
private void makeAd() { System.out.println("苹果的产品设计优雅、使用便捷"); }
private void record() { System.out.println("更新销售记录、更新库存数"); } }
|
至此,我们的代理模式就已经完成了,现在来看看如何使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public class ProxyPatternDemo { public static void main(String[] args) { Apple apple = new Apple();
Sell appleStore = new AppleStore(apple);
appleStore.sellPhone(); appleStore.sellPc(); } }
|
测试结果如下,符合预期
准确来说,这里我们所实现的代理模式实际上是静态代理,即代理角色需要提前编写好,在运行前就被确定下来了。而在很多框架实现中更多的是采用动态代理的方式,即代理类是在运行期时动态生成的
参考文献
- Head First 设计模式 弗里曼著