PHP設(shè)計(jì)模式之中介者模式(Mediator Pattern)入門(mén)與應(yīng)用案例詳解
本文實(shí)例講述了PHP設(shè)計(jì)模式之中介者模式(Mediator Pattern)。分享給大家供大家參考,具體如下:
咱們先來(lái)看下中介者模式(Mediator Pattern)的定義,它就是,用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互,這種模式又稱為調(diào)停者模式,它是一種對(duì)象行為型模式。
我們先來(lái)看用戶與用戶直接聊天的設(shè)計(jì)方案。
在這個(gè)方案設(shè)計(jì)的過(guò)程中,我們可以發(fā)揮想象,用戶對(duì)象之間存在很強(qiáng)的關(guān)聯(lián)性,將導(dǎo)致系統(tǒng)出現(xiàn)如下問(wèn)題:
- 系統(tǒng)結(jié)構(gòu)復(fù)雜:對(duì)象之間存在大量的相互關(guān)聯(lián)和調(diào)用,若有一個(gè)對(duì)象發(fā)生變化,則需要跟蹤和該對(duì)象關(guān)聯(lián)的其他所有對(duì)象,并進(jìn)行適當(dāng)處理
- 對(duì)象可重用性差:由于一個(gè)對(duì)象和其他對(duì)象具有很強(qiáng)的關(guān)聯(lián),若沒(méi)有其他對(duì)象的支持,一個(gè)對(duì)象很難被另一個(gè)系統(tǒng)或模塊重用,這些對(duì)象表現(xiàn)出來(lái)更像一個(gè)不可分割的整體,職責(zé)較為混亂
- 系統(tǒng)擴(kuò)展性低:增加一個(gè)新的對(duì)象需要在原有相關(guān)對(duì)象上增加引用,增加新的引用關(guān)系也需要調(diào)整原有對(duì)象,系統(tǒng)耦合度很高,對(duì)象操作很不靈活,擴(kuò)展性差
然而,在面向?qū)ο蟮能浖O(shè)計(jì)與開(kāi)發(fā)過(guò)程中,根據(jù)“單一職責(zé)原則”,我們應(yīng)該盡量將對(duì)象細(xì)化,使其只負(fù)責(zé)或呈現(xiàn)單一的職責(zé),但是,對(duì)于一個(gè)模塊來(lái)說(shuō),可能由很多對(duì)象構(gòu)成,而且這些對(duì)象之間可能存在相互的引用,為了減少對(duì)象兩兩之間復(fù)雜的引用關(guān)系,使之成為一個(gè)松耦合的系統(tǒng),我們需要使用中介者模式,這就是我們使用中介者模式的動(dòng)機(jī)。
來(lái)看下中介者模式包含的角色:
- Mediator: 抽象中介者,在里面定義了各個(gè)同事之間相互交互所需要的方法。
- ConcreteMediator: 具體中介者,它需要了解并為維護(hù)每個(gè)同事對(duì)象,并負(fù)責(zé)具體的協(xié)調(diào)各個(gè)同事對(duì)象的交互關(guān)系。
- Colleague:抽象同事類(lèi),通常實(shí)現(xiàn)成為抽象類(lèi),主要負(fù)責(zé)約束同事對(duì)象的類(lèi)型,并實(shí)現(xiàn)一些具體同事類(lèi)之間的公共功能
- ConcreteColleague:具體同事類(lèi),實(shí)現(xiàn)自己的業(yè)務(wù),需要與其他同事對(duì)象交互,就通知中介對(duì)象,中介對(duì)象會(huì)負(fù)責(zé)后續(xù)的交互
再來(lái)看下圖片感受下:
來(lái)看一個(gè)完整的實(shí)例:
- 我們有一個(gè)CD類(lèi)和一個(gè)MP3類(lèi),兩個(gè)類(lèi)的結(jié)構(gòu)相似。
- 我們需要在CD類(lèi)更新的時(shí)候,同步更新MP3類(lèi)。
- 傳統(tǒng)的做法就是在CD類(lèi)中實(shí)例化MP3類(lèi),然后去更新,但是這么做的話,代碼就會(huì)很難維護(hù),如果新增一個(gè)同樣的MP4類(lèi),那么就沒(méi)法處理了。
- 中介者模式很好的處理了這種情況,通過(guò)中介者類(lèi),CD類(lèi)中只要調(diào)用中介者這個(gè)類(lèi),就能同步更新這些數(shù)據(jù)。
代碼實(shí)例如下:
<?php class CD { public $band = ''; public $title = ''; protected $_mediator; public function __construct(MusicContainerMediator $mediator = NULL) { $this->_mediator = $mediator; } public function save() { //具體實(shí)現(xiàn)待定 var_dump($this); } public function changeBandName($bandname) { if ( ! is_null($this->_mediator)) { $this->_mediator->change($this, array("band" => $bandname)); } $this->band = $bandname; $this->save(); } } //MP3Archive類(lèi) class MP3Archive { protected $_mediator; public function __construct(MusicContainerMediator $mediator = NULL) { $this->_mediator = $mediator; } public function save() { //具體實(shí)現(xiàn)待定 var_dump($this); } public function changeBandName($bandname) { if ( ! is_null($this->_mediator)) { $this->_mediator->change($this, array("band" => $bandname)); } $this->band = $bandname; $this->save(); } } //中介者類(lèi) class MusicContainerMediator { protected $_containers = array(); public function __construct() { $this->_containers[] = "CD"; $this->_containers[] = "MP3Archive"; } public function change($originalObject, $newValue) { $title = $originalObject->title; $band = $originalObject->band; foreach ($this->_containers as $container) { if ( ! ($originalObject instanceof $container)) { $object = new $container; $object->title = $title; $object->band = $band; foreach ($newValue as $key => $val) { $object->$key = $val; } $object->save(); } } } } //測(cè)試實(shí)例 $titleFromDB = "Waste of a Rib"; $bandFromDB = "Never Again"; $mediator = new MusicContainerMediator(); $cd = new CD($mediator); $cd->title = $titleFromDB; $cd->band = $bandFromDB; $cd->changeBandName("Maybe Once More");
運(yùn)行結(jié)果:
object(MP3Archive)#3 (3) {
["_mediator":protected]=>
NULL
["title"]=>
string(14) "Waste of a Rib"
["band"]=>
string(15) "Maybe Once More"
}
object(CD)#2 (3) {
["band"]=>
string(15) "Maybe Once More"
["title"]=>
string(14) "Waste of a Rib"
["_mediator":protected]=>
object(MusicContainerMediator)#1 (1) {
["_containers":protected]=>
array(2) {
[0]=>
string(2) "CD"
[1]=>
string(10) "MP3Archive"
}
}
}
還有個(gè)實(shí)例,一起看下吧:
//抽象同事類(lèi),家教 abstract class Tutor{ protected $message; //個(gè)人信息 protected $mediator; //為家教服務(wù)的中介機(jī)構(gòu) function __construct($message,Mediator $mediator){ $this->message = $message; $this->mediator = $mediator; } //獲取個(gè)人信息 function getMessage(){ return $this->message; } //找學(xué)生 abstract function findStudent(); } //具體同事類(lèi),大學(xué)生家教 class UndergraduateTutor extends Tutor{ //家教類(lèi)型 public $type = "UndergraduateTutor"; function __construct($message,Mediator $mediator){ parent::__construct($message,$mediator); } //找學(xué)生,讓中介機(jī)構(gòu)代為尋找 function findStudent(){ $this->mediator->matchStudent($this); } } //具體同事類(lèi),高中生家教 class SeniorStudentTutor extends Tutor{ //家教類(lèi)型 public $type = "SeniorStudentTutor"; function __construct($message,Mediator $mediator){ parent::__construct($message,$mediator); } //找學(xué)生,讓中介機(jī)構(gòu)代為尋找 function findStudent(){ $this->mediator->matchStudent($this); } } //具體同事類(lèi),初中生家教 class MiddleStudentTutor extends Tutor{ //家教類(lèi)型 public $type = "MiddleStudentTutor"; function __construct($message,Mediator $mediator){ parent::__construct($message,$mediator); } //找學(xué)生,讓中介機(jī)構(gòu)代為尋找 function findStudent(){ $this->mediator->matchStudent($this); } } //抽象中介類(lèi) abstract class AbstractMediator{ abstract function matchStudent(Tutor $tutor); } //具體中介類(lèi),為家教匹配合適的學(xué)生 class Mediator extends AbstractMediator{ //定義其服務(wù)的所有家教,不在范圍內(nèi)的不服務(wù) private $serveObject = array("UndergraduateTutor","SeniorStudentTutor","MiddleStudentTutor"); //匹配學(xué)生 function matchStudent(Tutor $tutor){ for($i=0;$i<count($this->serveObject);$i++){ if($tutor->type == $this->serveObject[$i]){ $message = $tutor->getMessage(); echo "該家教個(gè)人信息為".print_r($message)."<br/>將為其匹配合適的學(xué)生"; break; } } if($i>=count($this->serveObject)){ echo "該家教不在我中介機(jī)構(gòu)服務(wù)范圍內(nèi)"; } } } //測(cè)試 $mediator = new Mediator(); $undergraduateTutor = new UndergraduateTutor(array("name"=>"張三","age"=>22),$mediator); $undergraduateTutor->findStudent(); //結(jié)果:該家教個(gè)人信息為 Array ( [name] => 張三 [age] => 22 ),將為其匹配合適的學(xué)生
好啦,本次記錄就到這里了。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
destoon出現(xiàn)驗(yàn)證碼不顯示時(shí)的緊急處理方法
這篇文章主要介紹了destoon出現(xiàn)驗(yàn)證碼不顯示時(shí)的緊急處理方法,非常實(shí)用,需要的朋友可以參考下2014-08-08詳解在YII2框架中使用UEditor編輯器發(fā)布文章
這篇文章主要介紹了在YII2框架中使用UEditor編輯器發(fā)布文章,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11在 Laravel 項(xiàng)目中使用 webpack-encore的方法
這篇文章主要介紹了在 Laravel 項(xiàng)目中使用 webpack-encore的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07php獲取qq用戶昵稱和在線狀態(tài)(實(shí)例分析)
獲取qq在線狀態(tài)官方已有API提供了,我們用另一種方法獲取qq用戶昵稱和在線狀態(tài),主要是為學(xué)習(xí)PHP。2013-10-10阿里云Win2016安裝Apache和PHP環(huán)境圖文教程
本文給大家講述的是在阿里云的WindowsServer2016上部署Apache和PHP的web環(huán)境,步驟非常細(xì)致,強(qiáng)烈推薦給大家2018-03-03thinkphp實(shí)現(xiàn)發(fā)送郵件密碼找回功能實(shí)例
這篇文章主要介紹了thinkphp實(shí)現(xiàn)發(fā)送郵件密碼找回功能的方法,以實(shí)例形式詳細(xì)講述了配置文件與功能代碼的實(shí)現(xiàn)方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-12-12