橋接模式,在程序世界中,其實就是組合/聚合的代名詞。爲何這麼說呢?熟悉面向對象的咱們都知道繼承的好處,子類能夠共享父類的不少屬性、功能。可是,繼承也會帶來一個問題,那就是嚴重的耦合性。父類的修改多少都會對子類產生影響,甚至一個方法或屬性的修改都有可能讓全部子類都去修改一遍。這樣就違背了開放封裝原則。而橋接就是爲了解決這個問題,它強調的是用組合/聚合的方式來共享一些能用的方法。相信你們必定想到了php中的trait,若是你在工做中使用過這個特性,那麼你就已經用過橋接模式了!php
GoF定義:將抽象部分與它的實現部分分離,使它們均可以獨立地變化。git
GoF類圖github
代碼實現設計模式
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。this
$impA = new ConcreteImplementorA();
$impB = new ConcreteImplementorB();
$ra = new RefinedAbstraction();
$ra->SetImplementor($impA);
$ra->Operation();
$ra->SetImplementor($impB);
$ra->Operation();
複製代碼
客戶端調用,咱們的抽象類使用不用的實現類就可讓操做方法變成多態的感受。阿里雲
咱們的手機有不一樣的型號,每一個型號又要生產大體相同但不一樣的配件。好比X1手機殼、貼膜、耳機;X2的手機殼、貼膜、耳機等。受限於成本的問題,咱們不會給每個型號的手機都去生產徹底不同的配套配件。而是去儘可能使用外部通用的配件(Implementor),讓每一種型號的手機(Abstraction)去進行組合(Bridge),搭配售賣給消費者。這樣,纔不至於讓咱們的手機品牌太早的消耗完融資關門大吉。看來,作企業和學設計模式還真是有不少相關之處哦!!spa
完整代碼:github.com/zhangyue050…設計
咱們的短信發送也能夠用橋接來實現。假設咱們有不少的短信模板,而後搭配不一樣的短信提供商進行短信的發送。這時,咱們就能夠用橋接模式來造成各類不一樣的組合。code
短信發送類圖
<?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();
// ......
複製代碼
說明
上次提到過虛擬機軟件的橋接網絡模式,它的做用是相似於把物理主機虛擬爲一個交換機,全部橋接設置的虛擬機鏈接到這個交換機的一個接口上,物理主機也一樣插在這個交換機當中,因此全部橋接下的網卡與網卡都是交換模式的,相互能夠訪問而不干擾。其實和咱們的設計模式很類似,將抽象對象看作是虛擬交換機,實現類就是虛擬機,經過對象的引用做爲網線將它們鏈接在一塊兒。看着簡單的模式但想深刻理解也是挺困難的吧?特別是它與其餘模式很相似的時候。下回咱們講的門面模式也是這樣,很好理解,但轉頭一想又會以爲跟其餘一些模式很類似,因此,仍是須要深刻的理解才能更好的掌握這些模式,話很少說,下回見!