|
| 1 | +# 代理 |
| 2 | + |
| 3 | +给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。 |
| 4 | + |
| 5 | + |
| 6 | +## UML |
| 7 | + |
| 8 | +* 抽象主题角色(Subject) |
| 9 | +* 代理主题角色(Proxy) |
| 10 | +* 真实主题角色(RealSubject) |
| 11 | + |
| 12 | + |
| 13 | +1. 远程代理(Remote Proxy):为一个位于不同地址空间的对象提供一个本地的代理对象。不同的地址空间可以在相同或不同的主机中。 |
| 14 | +2. 虚拟代理(Virtual Proxy):当创建一个对象需要消耗大量资源时,可以先创建一个消耗较少资源的虚拟代理来表示,当真正需要时再创建。 |
| 15 | +3. 保护代理(Protect Proxy):给不同的用户提供不同的对象访问权限。 |
| 16 | +4. 缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时存储空间,以使更多用户可以共享这些结果。 |
| 17 | +5. 智能引用代理(Smart Reference Proxy):当一个对象被引用时提供一些额外的操作,比如将对象被调用的次数记录下来等 |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +## 优缺点 |
| 22 | + |
| 23 | +* 优点 |
| 24 | + * 代理模式能够协调调用者和被调用者,降低系统耦合度 |
| 25 | + * 客户端针对抽象主题角色编程,如果要增加或替换代理类,无需修改源代码,符合开闭原则,系统扩展性好 |
| 26 | + |
| 27 | +* 缺点 |
| 28 | + * 增加了代理类和代理对象,增加了代理对象中的某些处理流程,可能会使得系统响应变慢 |
| 29 | + * 有的代理模式(如远程代理)实现代码较为复杂 |
| 30 | + |
| 31 | + |
| 32 | +## 使用场景 |
| 33 | + |
| 34 | +* 当客户端对象需要访问远程主机中的对象 —— 可以使用远程代理 |
| 35 | +* 当需要用一个资源消耗较少的对象来代表一个资源消耗较多的对象 —— 虚拟代理 |
| 36 | +* 当需要限制不同用户对一个独享的访问权限 —— 保护代理 |
| 37 | +* 当需要为一个频繁访问的操作结果提供临时存储空间 —— 缓冲代理 |
| 38 | +* 当需要为一个对象的访问提供一些额外的操作 —— 智能引用代理 |
| 39 | + |
| 40 | + |
| 41 | +## 用例 |
| 42 | + |
| 43 | +以前春运时,火车票一票难求,当时黄牛党应运而生, 购票人向黄牛购票, 黄牛最终从售票点起票后,再交易给购票人,其中购票人不需要到售票点排队购票,省时省力,只需多付些手续费. |
| 44 | + |
| 45 | +[code](../code/13_proxy) |
| 46 | + |
| 47 | +```c++ |
| 48 | +// seller_types.h |
| 49 | +#pragma once |
| 50 | +#include <iostream> |
| 51 | +#include <string> |
| 52 | +using namespace std; |
| 53 | + |
| 54 | +class Seller { |
| 55 | +public: |
| 56 | + virtual int lookupPrice(string from,string to) = 0; |
| 57 | +}; |
| 58 | + |
| 59 | +class TrainticketSeller :public Seller { |
| 60 | +public: |
| 61 | + int lookupPrice(string from, string to) { |
| 62 | + return 100; |
| 63 | + } |
| 64 | +}; |
| 65 | + |
| 66 | +class TicketScalper :public Seller { |
| 67 | +public: |
| 68 | + TicketScalper():m_realSeller(new TrainticketSeller){ |
| 69 | + |
| 70 | + } |
| 71 | + int lookupPrice(string from, string to) { |
| 72 | + int originalPrice = m_realSeller->lookupPrice(from, to); |
| 73 | + cout << "\nTicket [" << from << " - " << to << "] orignal price:" << originalPrice << endl; |
| 74 | + int addPrice = 10; |
| 75 | + return (originalPrice+addPrice); |
| 76 | + } |
| 77 | +private: |
| 78 | + Seller* m_realSeller; |
| 79 | +}; |
| 80 | +``` |
| 81 | +
|
| 82 | +```c++ |
| 83 | +// client.cpp |
| 84 | +#include "seller_types.h" |
| 85 | +using namespace std; |
| 86 | +
|
| 87 | +int main() { |
| 88 | +
|
| 89 | + Seller* seller = new TicketScalper(); |
| 90 | + string from = "Shanghai", to = "NanJing"; |
| 91 | + cout << "What is the price of ticket [" << from << " - " << to << "] ?"; |
| 92 | + int price = seller->lookupPrice(from, to); |
| 93 | + cout << "After addition fee 10, the ticket price is "<<price << endl; |
| 94 | + return 0; |
| 95 | +} |
| 96 | +``` |
0 commit comments