[toc]
## 舉個例子
**找房子如果沒有中介...**
1. 首先要知道自己要怎樣的房子:多大面積(多少平米),什么價位,是否有窗戶,是否有獨衛。
1. 去網上查找各種房源信息,找到最匹配的幾個戶型。
1. 之后要去電話咨詢,過濾虛假信息和過時信息。
1. 最后,也是最累人的一步,要去實地考查,看看真實的房子與網上的信息是否相符,房間是否有異味,周圍設施是否齊全。這一步你可能會從東城穿越西城,再來到南城,而后又折騰去北城……想想都累!
1. 最后的最后,你還要與各種脾性的房東進行周旋,去討價還價。

**如果有中介...**
-- “18平米左右,要有獨衛,要有窗戶,最好是朝南,有廚房更好!價位在2000左右。”
-- “上地西里有一間,但沒有廚房;當代城市家園有兩間,一間主臥,一間次臥,但衛生間是共用的;美和園有一間,比較適合你,但價格會貴一點。”

## 什么是中介模式?
> 這種由中介來承接房客與房東之間的交互的過程,在程序中叫做中介模式。用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。中介者模式又稱為調停者模式,它是一種對象行為型模式。
## 代碼示例
```php
<?php
//房源信息
class HouseInfo {
private $area;
private $price;
private $window;
private $bathroom;
private $kitchen;
private $address;
private $owner;
public function __construct($area, $price, $hasWindow, $bathroom, $kitchen, $address, $owner) {
$this->area = $area;
$this->price = $price;
$this->window = $hasWindow;
$this->bathroom = $bathroom;
$this->kitchen = $kitchen;
$this->address = $address;
$this->owner = $owner;
}
public function getAddress() {
return $this->address;
}
public function getOwnerName() {
return $this->owner->getName();
}
public function showInfo($isShowOwner = true) {
$res = "";
$res .= "面積 ";
$res .= strval($this->area);
$res .= "平米 " . PHP_EOL;
$res .= "價格 ";
$res .= strval($this->price);
$res .= "元 " . PHP_EOL;
$res .= "窗戶 ";
$res .= $this->window ? "有 " : "沒有 ";
$res .= PHP_EOL;
$res .= "衛生間 ";
$res .= $this->bathroom . PHP_EOL;
$res .= "廚房 ";
$res .= $this->kitchen ? "有 " : "沒有 ";
$res .= PHP_EOL;
$res .= "地址 ";
$res .= $this->getAddress() . PHP_EOL;
$res .= "房東 ";
$res .= $isShowOwner ? $this->getOwnerName() : "無";
$res .= PHP_EOL;
echo $res;
echo PHP_EOL;
}
}
//房屋中介
class HousingAgency {
private $houseInfos;
private $name;
public function __construct($name) {
$this->houseInfos = array();
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function addHouseInfo($houseInfo) {
array_push($this->houseInfos, $houseInfo);
}
public function removeHouseInfo($houseInfo) {
foreach ($this->houseInfos as $info) {
if ($info == $houseInfo) {
// 根據值, 從數組中刪除指定元素
$this->houseInfos = array_merge(array_diff($this->houseInfos, array($houseInfo)));
}
}
}
// 這里有一個將用戶描述信息轉換成搜索條件的邏輯。(為節省篇幅這里原樣返回描述)
public function getSearchCondition($description) {
return $description;
}
// 根據房源信息的各個屬性查找最匹配的信息。(為節省篇幅這里略去匹配的過程,全部輸出)
public function getMatchInfos($searchCondition) {
echo $this->getName() . "為您找以下最適合的房源:" . PHP_EOL;
foreach ($this->houseInfos as $info) {
$info->showInfo(false);
}
return $this->houseInfos;
}
// 與房東簽訂協議
public function signContract($houseInfo, $time) {
$res = "";
$res .= "{$this->getName()} 與房東 {$houseInfo->getOwnerName()} 簽訂";
$res .= "{$houseInfo->getAddress()} 的房子的的租賃合同,租期 {$time} 年。" . PHP_EOL;
$res .= "合同期內 {$this->getName()} 有權對其進行使用和轉租!";
echo $res;
echo PHP_EOL;
echo PHP_EOL;
}
public function signContracts($time) {
foreach ($this->houseInfos as $info) {
$this->signContract($info, $time);
}
}
}
//房東
class HouseOwner {
private $name;
private $address;
private $houseInfo;
public function __construct($name, $address) {
$this->name = $name;
$this->address = $address;
$this->houseInfo = null;
}
public function getName() {
return $this->name;
}
public function getAddress() {
return $this->address;
}
public function setHouseInfo($area, $price, $hasWindow, $bathroom, $kitchen) {
$this->houseInfo = new HouseInfo($area, $price, $hasWindow, $bathroom, $kitchen, $this->address, $this);
}
public function publishHouseInfo($agency) {
$agency->addHouseInfo($this->houseInfo);
echo $this->getName() . "在" . $agency->getName() . "發布房源出租信息:" . PHP_EOL;
$this->houseInfo->showInfo();
}
}
//房客,租房人
class Custom {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function findHouse($description, $agency) {
echo "我是 {$this->getName()}, 我想要找一個{$description}的房子";
echo PHP_EOL;
echo PHP_EOL;
return $agency->getMatchInfos($agency->getSearchCondition($description));
}
//去看房,選擇最實用的房子。(這里省略看房的過程, 返回最后一個)
public function seeHouse($houseInfos) {
return end($houseInfos);
}
//與中介簽訂協議
public function signContract($houseInfo, $agency, $time) {
echo "{$this->getName()} 與中介{$agency->getName()} 簽訂{$houseInfo->getAddress()} 的房子的租賃合同租期{$time} 年。合同期內{$this->name} 有權對其進行使用!";
}
}
$myHome = new HousingAgency("我愛我家");
$zhangsan = new HouseOwner("張三", "上地西里");
$zhangsan->setHouseInfo(20, 2500, 1, "獨立衛生間", 0);
$zhangsan->publishHouseInfo($myHome);
$lisi = new HouseOwner("李四", "當代城市家園");
$lisi->setHouseInfo(16, 1800, 1, "公用衛生間", 0);
$lisi->publishHouseInfo($myHome);
$wangwu = new HouseOwner("王五", "金隅美和園");
$wangwu->setHouseInfo(18, 2600, 1, "獨立衛生間", 1);
$wangwu->publishHouseInfo($myHome);
echo PHP_EOL;
$myHome->signContracts(3);
echo PHP_EOL;
$tony = new Custom("Tony");
$houseInfos = $tony->findHouse("18平米左右,要有獨衛,要有窗戶,最好是朝南,有廚房更好!價位在2000左右", $myHome);
echo PHP_EOL;
echo "正在看房,尋找最合適的住巢……";
echo PHP_EOL;
$AppropriateHouse = $tony->seeHouse($houseInfos);
$tony->signContract($AppropriateHouse, $myHome, 1);
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
張三在我愛我家發布房源出租信息:
面積 20平米
價格 2500元
窗戶 有
衛生間 獨立衛生間
廚房 沒有
地址 上地西里
房東 張三
李四在我愛我家發布房源出租信息:
面積 16平米
價格 1800元
窗戶 有
衛生間 公用衛生間
廚房 沒有
地址 當代城市家園
房東 李四
王五在我愛我家發布房源出租信息:
面積 18平米
價格 2600元
窗戶 有
衛生間 獨立衛生間
廚房 有
地址 金隅美和園
房東 王五
我愛我家 與房東 張三 簽訂上地西里 的房子的的租賃合同,租期 3 年。
合同期內 我愛我家 有權對其進行使用和轉租!
我愛我家 與房東 李四 簽訂當代城市家園 的房子的的租賃合同,租期 3 年。
合同期內 我愛我家 有權對其進行使用和轉租!
我愛我家 與房東 王五 簽訂金隅美和園 的房子的的租賃合同,租期 3 年。
合同期內 我愛我家 有權對其進行使用和轉租!
我是 Tony, 我想要找一個18平米左右,要有獨衛,要有窗戶,最好是朝南,有廚房更好!價位在2000左右的房子
我愛我家為您找以下最適合的房源:
面積 20平米
價格 2500元
窗戶 有
衛生間 獨立衛生間
廚房 沒有
地址 上地西里
房東 無
面積 16平米
價格 1800元
窗戶 有
衛生間 公用衛生間
廚房 沒有
地址 當代城市家園
房東 無
面積 18平米
價格 2600元
窗戶 有
衛生間 獨立衛生間
廚房 有
地址 金隅美和園
房東 無
正在看房,尋找最合適的住巢……
Tony 與中介我愛我家 簽訂金隅美和園 的房子的租賃合同租期1 年。合同期內Tony 有權對其進行使用!
Process finished with exit code 0
```
## 優缺點
**優點**
1. 將原本分布于多個對象間的行為集中在一起,作為一個獨立的概念并將其封裝在一個對象中,簡化了對象之間的交互。
1. 將多個調用者與多個實現者間多對多的交互關系,轉換為一對多的交互,一對多的關系更易于理解、維護和擴展。
1. 大大減少了多個對象相互交差引用的情況。
**缺點**
1. 中介者承接了所有的交互邏輯,交互的復雜度變成了中介的復雜度,中介者類會變得越來越龐大和復雜,難于維護。
1. 中介者出問題會導致多個使用者同時出問題。
## 使用場景
1. 一組對象以定義良好但是復雜的方式進行通信。產生的相互依賴關系結構混亂且難以理解。
1. 一個對象引用其他很多對象并且直接與這些對象通信,導致難以復用該對象。
1. 想通過一個中間類來封裝多個類中的行為,而又不想生成太多的子類。