首頁  >  文章  >  後端開發  >  淺談PHP中的橋接模式

淺談PHP中的橋接模式

青灯夜游
青灯夜游轉載
2021-07-21 19:53:232841瀏覽

在之前的文章《一起聊聊PHP中的備忘錄模式》中我們介紹了PHP中的備忘錄模式,下面這篇文章帶大家了解一下PHP設計模式中的橋接模式。

淺談PHP中的橋接模式

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

Gof類別圖及解釋

GoF定義:將抽象部分與它的實作部分分離,使它們都可以獨立地變更。

GoF類別圖

淺談PHP中的橋接模式

#程式碼實作

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

#實例

我們的簡訊傳送也可以用橋接來實現。假設我們有很多的簡訊模板,然後搭配不同的簡訊提供者進行簡訊的發送。這時,我們就可以用橋接模式來形成各種不同的組合。

簡訊發送類別圖

淺談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 &#39;您的登录验证码是【AAA】,请不要泄露给他人【XXX公司】!&#39;, PHP_EOL;
    }
}
class RegisterMessage implements MessageTemplate
{
    public function GetTemplate()
    {
        echo &#39;您的注册验证码是【BBB】,请不要泄露给他人【XXX公司】!&#39;, PHP_EOL;
    }
}
class FindPasswordMessage implements MessageTemplate
{
    public function GetTemplate()
    {
        echo &#39;您的找回密码验证码是【CCC】,请不要泄露给他人【XXX公司】!&#39;, 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 &#39;阿里云开始发送短信:&#39;;
        $this->template->GetTemplate();
    }
}

class JiGuangService extends MessageService
{
    public function Send()
    {
        echo &#39;极光开始发送短信:&#39;;
        $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,那就不要猶豫的用繼承吧
原文網址:https://juejin.cn/post/6844903986655395848

#作者:硬派專案經理

推薦學習:《PHP影片教學

以上是淺談PHP中的橋接模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除