[toc]
## 舉個例子
**代收快遞**
* 周四下單, 周末雙休, 你以為周末快遞能到, 所以選了家里的地址
* 結果周五快遞就到了, 但是你在上班
* 你讓宅在家里的鄰居幫你代收
## 代碼示例
```php
<?php
// 接收包裹
class ReceiveParcel {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function receive($parcelContent) {
}
}
// Tony接收
class TonyReception extends ReceiveParcel {
private $phoneNum;
public function __construct($name, $phoneNum) {
parent::__construct($name);
$this->phoneNum = $phoneNum;
}
public function getPhoneNum() {
return $this->phoneNum;
}
public function receive($parcelContent) {
echo "貨物主人:{$this->getName()}, 手機號:{$this->getPhoneNum()} ";
echo "收到一個包裹, 包裹內容: {$parcelContent}" . PHP_EOL;
}
}
// Wendy接收
class WendyReception extends ReceiveParcel {
private $receiver;
public function __construct($name, $receiver) {
parent::__construct($name);
$this->receiver = $receiver;
}
public function receive($parcelContent) {
echo "我是" . $this->receiver->getName() . "的朋友, 我來幫他代收快遞!" . PHP_EOL;
if ($this->receiver) {
$this->receiver->receive($parcelContent);
}
echo "代收人:" . $this->getName();
}
}
$tony = new TonyReception("Tony", "18512345678");
$wendy = new WendyReception("Wendy", $tony);
$wendy->receive("雪地靴");
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
我是Tony的朋友, 我來幫他代收快遞!
貨物主人:Tony, 手機號:18512345678 收到一個包裹, 包裹內容: 雪地靴
代收人:Wendy
Process finished with exit code 0
```
## 代碼說明
> 包裹實際上是 Tony 的,但是 Wendy 代替 Tony 的身份幫忙接收了包裹,Wendy 需要使用 Tony 的身份并獲得快遞員的驗證(Tony 手機號)才能成功接收包裹。
## 什么是代理模式?
1. 給某一個對象提供一個代理,并由代理對象控制對原對象的引用。
1. 一個客戶不想或者不能直接引用一個對象,此時可以通過一個稱之為“代理”的第三者來實現間接引用。
1. 如上面的示例中,Tony 因為不在家,所以不能親自接收包裹,但他可以叫 Wendy 來代他接收,這里 Wendy 就是代理,她代理了 Tony 的身份去接收快遞。

## 設計要點
1. **主題(Subject)**:定義“操作/活動/任務”的接口類。
1. **真實主題(RealSubject)**:真正完成“操作/活動/任務”的具體類。
1. **代理主題(ProxySubject)**:代替真實主題完成“操作/活動/任務”的代理類
## 優缺點
**代理模式的優點**
1. 代理模式能夠協調調用者和被調用者,在一定程度上降低了系統的耦合度。
1. 可以靈活地隱藏被代理對象的部分功能和服務,也增加額外的功能和服務。
**代理模式的缺點**
1. 由于在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
1. 實現代理模式需要額外的工作,有些代理模式的實現非常復雜。
## 應用場景
1. 不想或者不能直接引用一個對象時
如在移動端加載網頁信息時,因為下載真實大圖比較耗費流量和性能,可以用一個小圖代替進行渲染(用一個代理對象去下載小圖),在真正點擊圖片時,才去下載大圖,顯示大圖效果。還有 HTML 中的占位符,其實也是代理的思想。
1. 想對一個對象的功能進行加強時
如在字體(Font)渲染時,對粗體(BoldFont)進行渲染時,可使用字體 Font 對象進行代理,只要在對 Font 進行渲染后,進行一步加粗的操作即可。