橋接模式,在程式世界中,其實就是組合/聚合的代名詞,為什么這么說呢?熟悉面向物件的我們都知道繼承的好處,子類可以共享父類的很多屬性、功能,但是,繼承也會帶來一個問題,那就是嚴重的耦合性,父類的修改多少都會對子類產生影響,甚至一個方法或屬性的修改都有可能讓所有子類都去修改一遍,這樣就違背了開放封裝原則,而橋接就是為了解決這個問題,它強調的是用組合/聚合的方式來共享一些能用的方法,相信大家一定想到了php中的trait,如果你在作業中使用過這個特性,那么你就已經用過橋接模式了!
Gof類圖及解釋
GoF定義:將抽象部分與它的實作部分分離,使它們都可以獨立地變化,
GoF類圖

代碼實作
interface Implementor
{
public function OperationImp();
}
class ConcreteImplementorA implements Implementor
{
public function OperationImp()
{
echo '具體實作A', PHP_EOL;
}
}
class ConcreteImplementorB implements Implementor
{
public function OperationImp()
{
echo '具體實作B', PHP_EOL;
}
}
我們先來定義實作介面以及它們具體的實作,也就是真正要執行的功能,就像是配接器模式中的Adaptee,
abstract class Abstraction
{
protected $imp;
public function SetImplementor(Implementor $imp)
{
$this->imp = $imp;
}
abstract public function Operation();
}
class RefinedAbstraction extends Abstraction
{
public function Operation()
{
$this->imp->OperationImp();
}
}
定義抽象類的介面,并維護一個對實作的參考,具體的抽象類的實作方法中,我們直接呼叫實作介面的真實操作方法,類似于配接器中的Adapter,
$impA = new ConcreteImplementorA();
$impB = new ConcreteImplementorB();
$ra = new RefinedAbstraction();
$ra->SetImplementor($impA);
$ra->Operation();
$ra->SetImplementor($impB);
$ra->Operation();
客戶端呼叫,我們的抽象類使用不用的實作類就可以讓操作方法變成多型的感覺,
- 在原始碼解釋中,我們會發現,這個模式和配接器模式非常相似,但是,配接器的目的是為了幫助兩個不太相關的類,讓它們能夠協同作業,實作中間轉換作業,而橋接則是為了讓方法的行為解除繼承耦合,方便地添加、修改,動態呼叫行為,讓抽象介面和實作部分可以獨立進行改變
- 讓抽象介面和實作部分可以獨立進行改變的意思是,只要維護了實作介面的參考,我們的實作介面的具體實作類可以是完全不同的類,里面有不同的功能,并且可以任意改變,讓實作來自己決定它自己是什么,
- 橋接模式的優點:分享介面及其實作部分、提高可擴充性、實作細節對客戶透明
- 橋接模式最主要解決的問題就是繼承的不斷增長而帶來的緊耦合問題
- 組合與聚合:聚合是弱關系,A可以包含B,但B不是A的一部分;組合是強關系,A包含B,B也是A的一部分,整體和部分的關系
我們的手機有不同的型號,每個型號又要生產大致相同但不同的配件,比如X1手機殼、貼膜、耳機;X2的手機殼、貼膜、耳機等,受限于成本的問題,我們不會給每一個型號的手機都去生產完全不一樣的配套配件,而是去盡量使用外部通用的配件(Implementor),讓每一種型號的手機(Abstraction)去進行組合(Bridge),搭配售賣給消費者,這樣,才不至于讓我們的手機品牌太早的消耗完融資關門大吉,看來,做企業和學設計模式還真是有很多相關之處哦!!
完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/18.bridge/source/bridge.php
實體
我們的短信發送也可以用橋接來實作,假設我們有很多的短信模板,然后搭配不同的短信提供商進行短信的發送,這時,我們就可以用橋接模式來形成各種不同的組合,
短信發送類圖

完整原始碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/18.bridge/source/bridge-message.php
<?php
interface MessageTemplate
{
public function GetTemplate();
}
class LoginMessage implements MessageTemplate
{
public function GetTemplate()
{
echo '您的登錄驗證碼是【AAA】,請不要泄露給他人【XXX公司】!', PHP_EOL;
}
}
class RegisterMessage implements MessageTemplate
{
public function GetTemplate()
{
echo '您的注冊驗證碼是【BBB】,請不要泄露給他人【XXX公司】!', PHP_EOL;
}
}
class FindPasswordMessage implements MessageTemplate
{
public function GetTemplate()
{
echo '您的找回密碼驗證碼是【CCC】,請不要泄露給他人【XXX公司】!', PHP_EOL;
}
}
abstract class MessageService
{
protected $template;
public function SetTemplate($template)
{
$this->template = $template;
}
abstract public function Send();
}
class AliYunService extends MessageService
{
public function Send()
{
echo '阿里云開始發送短信:';
$this->template->GetTemplate();
}
}
class JiGuangService extends MessageService
{
public function Send()
{
echo '極光開始發送短信:';
$this->template->GetTemplate();
}
}
// 三個短信模板
$loginTemplate = new LoginMessage();
$registerTemplate = new RegisterMessage();
$findPwTemplate = new FindPasswordMessage();
// 兩個短信服務商
$aliYun = new AliYunService();
$jg = new JiGuangService();
// 隨意組合
// 極光發注冊短信
$jg->SetTemplate($registerTemplate);
$jg->Send();
// 阿里云發登錄短信
$aliYun->SetTemplate($loginTemplate);
$aliYun->Send();
// 阿里云發找回密碼短信
$aliYun->SetTemplate($findPwTemplate);
$aliYun->Send();
// 極光發登錄短信
$jg->SetTemplate($loginTemplate);
$jg->Send();
// ......
說明
- 這就是一種聚合模式,模板并不是短信發送的一部分,我們不使用模板直接發送也可以,它們沒有強關系
- 短信發送商的發送方法無需改變,只需要傳入不同的短信模板就可以實作各種模板的快速發送
- 在不確定是否一定是is-a的關系的情況下,更推薦用橋接模式這種組合/聚合形式的設計方法,如果確定當前的類關系是is-a,那么就不要猶豫的用繼承吧
下期看點
上次提到過虛擬機軟體的橋接網路模式,它的作用是類似于把物理主機虛擬為一個交換機,所有橋接設定的虛擬機連接到這個交換機的一個介面上,物理主機也同樣插在這個交換機當中,所以所有橋接下的網卡與網卡都是交換模式的,相互可以訪問而不干擾,其實和我們的設計模式很相似,將抽象物件看做是虛擬交換機,實作類就是虛擬機,通過物件的參考作為網線將它們連接在一起,看著簡單的模式但想深入理解也是挺困難的吧?特別是它與其他模式很類似的時候,下回我們講的門面模式也是這樣,很好理解,但轉頭一想又會覺得跟其他一些模式很相似,所以,還是需要深入的理解才能更好的掌握這些模式,話不多說,下回見!
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/243123.html
標籤:PHP
上一篇:java物件
下一篇:關于資料抓取很多新人的誤區
