PHP設計模式之橋接模式 Bridge
橋接模式屬於結構型的設計模式
將實現與抽象放在兩個不同的類層次中,使兩個層次可以獨立改變
bridge 模式是基於最小設計原則,通過封裝,聚合及繼承等行為讓不同的類承擔不同的職責,主要的特點就是將抽象與實現分離,從而保證各部分的獨立性以及應對
他們功能的擴充套件
- 生活場景引入:
現在的生活都離不開手機,手機中又有不同的品牌,小米,華為,三星,蘋果。每一種手機的設計又不一樣,比如最開始的翻蓋手機,直板手機,到現在的全面屏手機,
假如現在的每個手機廠商都是最開始從翻蓋手機做起,雖然手機的樣子不一樣,但是手機的主要功能還是沒有變的,[開機,打電話,發簡訊,關機]這些個最基本的功能
都是會有的。那麼如果不適用設計模式來解決這個問題,我們就會有一下的方式:有一個手機的基類,定義了手機的基本功能,然後是各大品牌廠商繼承這個積累做手機,
最後廠商根據不同形態的手機做出對應的定製化的手機功能,如果未來發展需要做一款,隱形手機,那麼就需要再去加一個隱形收的模板,最後,各大廠商再去繼承這個隱
形手機的模板,再去做適配,要新增很多東西去適配,不利於維護和發展,而且如果還要再去加一個功能,那麼每個手機都要去加這個功能,很難維護
- 根據以上場景的匯入,現在就有了橋接模式為我們程式解決這個問題。
- 定義一個品牌介面類,裡面實現了
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();
- 輸出結果
//小米手機打電話
//摺疊樣式手機
//小米手機開機
//摺疊樣式手機
//小米手機關機
//摺疊樣式手機
//============================
//華為手機打電話
//摺疊樣式手機
//華為手機開機
//摺疊樣式手機
//華為手機關機
//摺疊樣式手機
//============================
//華為手機開機
//直板樣式手機
//華為手機打電話
//直板樣式手機
//華為手機關機
//直板樣式手機
- 一般框架中實際案例:
- 定義了一個
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地址