PHP 設計模式之橋接模式

echo_dump發表於2020-07-04

PHP設計模式之橋接模式 Bridge

  • 橋接模式屬於結構型的設計模式

  • 將實現與抽象放在兩個不同的類層次中,使兩個層次可以獨立改變

  • bridge 模式是基於最小設計原則,通過封裝,聚合及繼承等行為讓不同的類承擔不同的職責,主要的特點就是將抽象與實現分離,從而保證各部分的獨立性以及應對
    他們功能的擴充套件

  1. 生活場景引入:

現在的生活都離不開手機,手機中又有不同的品牌,小米,華為,三星,蘋果。每一種手機的設計又不一樣,比如最開始的翻蓋手機,直板手機,到現在的全面屏手機,
假如現在的每個手機廠商都是最開始從翻蓋手機做起,雖然手機的樣子不一樣,但是手機的主要功能還是沒有變的,[開機,打電話,發簡訊,關機]這些個最基本的功能
都是會有的。那麼如果不適用設計模式來解決這個問題,我們就會有一下的方式:有一個手機的基類,定義了手機的基本功能,然後是各大品牌廠商繼承這個積累做手機,
最後廠商根據不同形態的手機做出對應的定製化的手機功能,如果未來發展需要做一款,隱形手機,那麼就需要再去加一個隱形收的模板,最後,各大廠商再去繼承這個隱
形手機的模板,再去做適配,要新增很多東西去適配,不利於維護和發展,而且如果還要再去加一個功能,那麼每個手機都要去加這個功能,很難維護

傳統的現實方式

  1. 根據以上場景的匯入,現在就有了橋接模式為我們程式解決這個問題。

橋接模式

  • 定義一個品牌介面類,裡面實現了call(), open(), close()這些基本的手機都有的功能,之後由品牌,小米,華為,蘋果去實現介面
interface BrandInterface
{
    public function call();

    public function open();

    public function close();
}

class XiaoMiBrand implements BrandInterface
{

    public function call()
    {
        // TODO: Implement call() method.
        printf("小米手機打電話\n");
    }

    public function open()
    {
        // TODO: Implement open() method.
        printf("小米手機開機\n");
    }

    public function close()
    {
        // TODO: Implement close() method.
        printf("小米手機關機\n");
    }
}

class HuaWeiBrand implements BrandInterface
{

    public function call()
    {
        // TODO: Implement call() method.
        printf("華為手機打電話\n");
    }

    public function open()
    {
        // TODO: Implement open() method.
        printf("華為手機開機\n");
    }

    public function close()
    {
        // TODO: Implement close() method.
        printf("華為手機關機\n");
    }
}
  • 定義一個抽象類(手機抽象類),在這個抽象類中,首先聚合了品牌Brand,然後定義手機的call(),open(),close()方法,對應的方法裡,都是聚合
    Brand介面的抽象類實現呼叫的。

  • 最後是繼承抽象類的直板手機,摺疊手機和全面屏手機,根據不同樣式的手機再做定製化的功能

abstract class Phone
{
    protected $brand;

    public function __construct(BrandInterface $brand)
    {
        $this->brand = $brand;
    }

    public function open()
    {
        $this->brand->open();
    }

    public function close()
    {
        $this->brand->close();
    }

    public function call()
    {
        $this->brand->call();
    }
}

class FoldedPhone extends Phone
{
    public function open()
    {
        parent::open(); // TODO: Change the autogenerated stub

        printf("摺疊樣式手機\n");
    }

    public function close()
    {
        parent::close(); // TODO: Change the autogenerated stub

        printf("摺疊樣式手機\n");
    }

    public function call()
    {
        parent::call(); // TODO: Change the autogenerated stub

        printf("摺疊樣式手機\n");
    }
}

class UpRightPhone extends Phone
{
    public function open()
    {
        parent::open(); // TODO: Change the autogenerated stub

        printf("直板樣式手機\n");
    }

    public function close()
    {
        parent::close(); // TODO: Change the autogenerated stub

        printf("直板樣式手機\n");
    }

    public function call()
    {
        parent::call(); // TODO: Change the autogenerated stub

        printf("直板樣式手機\n");
    }
}
  • 這裡抽象類Phone就是一個橋樑,它並沒有具體實現自己的方法,只是動態的呼叫不同品牌手機的對應方法

  • 測試呼叫

class Client
{
    public function __construct()
    {
        $phone1 = new FoldedPhone(new XiaoMiBrand());

        $phone1->call();

        $phone1->open();

        $phone1->close();
        printf("============================\n");
        $phone2 = new FoldedPhone(new HuaWeiBrand());

        $phone2->call();

        $phone2->open();

        $phone2->close();
        printf("============================\n");
        $phone3 = new UpRightPhone(new HuaWeiBrand());

        $phone3->open();

        $phone3->call();

        $phone3->close();
    }
}

require './../vendor/autoload.php';

new Client();
  • 輸出結果
//小米手機打電話
//摺疊樣式手機
//小米手機開機
//摺疊樣式手機
//小米手機關機
//摺疊樣式手機
//============================
//華為手機打電話
//摺疊樣式手機
//華為手機開機
//摺疊樣式手機
//華為手機關機
//摺疊樣式手機
//============================
//華為手機開機
//直板樣式手機
//華為手機打電話
//直板樣式手機
//華為手機關機
//直板樣式手機
  1. 一般框架中實際案例:
  • 定義了一個 ConnectionInterface連線介面,Connection實現了連線介面
interface ConnectionInterface
{

}

class Connection implements ConnectionInterface
{

}
  • 下面是mysql, pgslq, sqLite, sqServer具體的實現
class MySqlConnection extends Connection
{

}

class PostgresConnection extends Connection
{

}

class SQLiteConnection extends Connection
{

}

class SqlServerConnection extends Connection
{

}
  • 定義一個Builder類,在構造方法中,傳入ConnectionInterface介面。Builder類就相當於一個橋
class Builder
{
    protected $connection;

    public function __construct(ConnectionInterface $connection)
    {
        $this->connection = $connection;
    }


    public function cursor()
    {
        if (is_null($this->columns)) {
            $this->columns = ['*'];
        }

        return $this->connection->cursor(
            $this->toSql(), $this->getBindings(), ! $this->useWritePdo
        );
    }

    public function exists()
    {
        $results = $this->connection->select(
            $this->grammar->compileExists($this), $this->getBindings(), ! $this->useWritePdo
        );

        // If the results has rows, we will get the row and see if the exists column is a
        // boolean true. If there is no results for this query we will return false as
        // there are no rows for this query at all and we can return that info here.
        if (isset($results[0])) {
            $results = (array) $results[0];

            return (bool) $results['exists'];
        }

        return false;
    }

    public function update(array $values)
    {
        $sql = $this->grammar->compileUpdate($this, $values);

        return $this->connection->update($sql, $this->cleanBindings(
            $this->grammar->prepareBindingsForUpdate($this->bindings, $values)
        ));
    }

    //......還有很多
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

LIYi ---- github地址

相關文章