设计模式(14):代理模式PROXY

代理模式

意图

为其他对象提供一种代理以控制对这个对象的访问。


使用场景

代理对象目标是控制它所代理的对象的初始化与访问。一个常见的应用场景是,在创建一些实例化开销较大的对象时,代理可以将创建过程推迟到真正需要该对象的时候。


结构

代理模式结构如下
ShowImage

  • Proxy

    – 保存一个引用使得代理可以访问实体。若RealObject和Subject的接口相同,Proxy会引用Subject。

    – 提供一个与Subject的接口相同的接口,这样代理就可以用来替代RealObject。

    – 控制对RealSubject的存取,并可能负责创建和删除它。

  • Subject

    – 定义RealObject和Proxy的共用接口,这样就在任何使用RealObject的地方都可以使用Proxy。

  • RealObject

    – 定义Proxy所代表的实体。

协作

代理根据其种类,在适当的时候向RealObject转发请求。

优点

  • 职责清晰地分离了
  • 扩展性良好
  • 动态代理可以在运行阶段指定代理的对象

代理模式实现(Implement)

案例

现在很多人都使用最新款的苹果手机Iphone7,有些人因为Iphone的高昂售价望而止步,为了节约钱,一部分人做起了代购港行美行Iphone的生意。在这个例子中,使用静态代理,港行Iphone7商店跟京东商城就是我们的RealObject,而代购就是Proxy。

代码实现

卖手机的接口

1
2
3
public interface SellSmartPhone {
void sellIphone7();
}

京东商城

1
2
3
4
5
6
7
8
9
10
11
public class JdOnlineStore implements SellSmartPhone {
public JdOnlineStore() {
System.out.println("欢迎光临京东商城...");
}
@Override
public void sellIphone7() {
System.out.println("售卖国行Iphone7...");
System.out.println("价格为5699元...");
}
}

香港百老汇

1
2
3
4
5
6
7
8
9
10
11
public class HkBroadwayStore implements SellSmartPhone {
public HkBroadwayStore() {
System.out.println("欢迎光临香港百老汇...");
}
@Override
public void sellIphone7() {
System.out.println("售卖港行Iphone7...");
System.out.println("价格为5699港币...");
}
}

Iphone代购,可以看到,代理类是在需要HkBroadWayStore(RealObject)的时候才进行实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SmartPhoneAgent implements SellSmartPhone {
private HkBroadwayStore hkBroadwayStore;
public SmartPhoneAgent() {
System.out.println("欢迎来到XXX手机代购店...");
}
@Override
public void sellIphone7() {
System.out.println("代购去香港买港行Iphone7...");
hkBroadwayStore = new HkBroadwayStore();
hkBroadwayStore.sellIphone7();
System.out.println("代购成功购买Iphone7...");
System.out.println("代购将Iphone7运回大陆地区进行贩卖...");
}
}

购买手机

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
public class ProxyDemoTest {
@Test
public void purchaseIphone7InMainland() {
System.out.println("去京东商城购买Iphone7");
System.out.println("--------------------");
System.out.println("打开京东商城");
JdOnlineStore jdOnlineStore = new JdOnlineStore();
jdOnlineStore.sellIphone7();
System.out.println("客户成功购买Iphone7...");
System.out.println("--------------------");
}
@Test
public void purchaseIphone7InHongKong() {
System.out.println("去香港购买Iphone7");
System.out.println("--------------------");
System.out.println("逛香港百老汇");
HkBroadwayStore hkBroadwayStore = new HkBroadwayStore();
hkBroadwayStore.sellIphone7();
System.out.println("客户成功购买Iphone7...");
System.out.println("--------------------");
}
@Test
public void purchaseIphone7InAgent() {
System.out.println("去XXX代购店购买Iphone7");
System.out.println("--------------------");
System.out.println("浏览XXX代购店");
SmartPhoneAgent smartPhoneAgent = new SmartPhoneAgent();
smartPhoneAgent.sellIphone7();
System.out.println("客户成功购买Iphone7...");
System.out.println("--------------------");
}
}

总结

回顾一下之前的装饰模式,发现装饰模式的结构跟代理模式非常相似,但是他们却不一样。装饰模式的目的是为目的对象动态的增加新的功能,而代理模式的目的是为了对目的对象进行控制。装饰模式在Decorator类实例化时会将需要装饰的对象传入构造器,而代理模式则是动态的分配一个对象。代理模式的实际使用场景非常广泛,例如在AOP(面向切面编程)时就使用了代理模式。

参考代码

------ 本文结束 ------

版权声明


BillyYccc's blog by Billy Yuan is licensed under a Creative Commons BY-NC-SA 4.0 International License.
本文原创于BillyYccc's Blog,转载请注明原作者及出处!