本篇文章是學習PHP中常用的三種設計模式的筆記及總結,不管采用哪一門語言開發什麼,幾乎都會使用到設計模式,我們為什麼需要設計模式呢?它的誕生對於我們開發人員來說有什麼樣的作用與意義呢?
相信做iOS開發的人員對設計模式也會挺熟悉吧?比如單例設計模式、工廠設計模式、觀察者模式、MVC框架結構設計模式等。
接下來我們一起來學習PHP中最常用的三種設計模式:單例設計模式、工廠設計模式和觀察者設計模式。
單例設計模式
所謂單例模式,即在應用程序中最多只有該類的一個實例存在,一旦創建,就會一直存在於內存中!
單例設計模式常應用於數據庫類設計,采用單例模式,只連接一次數據庫,防止打開多個數據庫連接。
一個單例類應具備以下特點:
單例類不能直接實例化創建,而是只能由類本身實例化。因此,要獲得這樣的限制效果,構造函數必須標記為private,從而防止類被實例化。
需要一個私有靜態成員變量來保存類實例和公開一個能訪問到實例的公開靜態方法。
在PHP中,為了防止他人對單例類實例克隆,通常還為其提供一個空的私有__clone()
方法。
單例模式的例子:
<?php /** * Singleton of Database */ class Database { // We need a static private variable to store a Database instance. privatestatic $instance; // Mark as private to prevent it from being instanced. privatefunction__construct() { // Do nothing. } privatefunction__clone() { // Do nothing. } publicstatic functiongetInstance() { if (!(self::$instanceinstanceofself)) { self::$instance = newself(); } returnself::$instance; } } $a =Database::getInstance(); $b =Database::getInstance(); // true var_dump($a === $b);
工廠設計模式
工廠設計模式常用於根據輸入參數的不同或者應用程序配置的不同來創建一種專門用來實例化並返回其對應的類的實例。
我們舉例子,假設矩形、圓都有同樣的一個方法,那麼我們用基類提供的API來創建實例時,通過傳參數來自動創建對應的類的實例,他們都有獲取周長和面積的功能。
<?php interfaceInterfaceShape { functiongetArea(); functiongetCircumference(); } /** * 矩形 */ class Rectangle implementsInterfaceShape { private $width; private $height; publicfunction__construct($width, $height) { $this->width = $width; $this->height = $height; } publicfunctiongetArea() { return $this->width* $this->height; } publicfunctiongetCircumference() { return 2 * $this->width + 2 * $this->height; } } /** * 圓形 */ class Circle implementsInterfaceShape { private $radius; function__construct($radius) { $this->radius = $radius; } publicfunctiongetArea() { return M_PI * pow($this->radius, 2); } publicfunctiongetCircumference() { return 2 * M_PI * $this->radius; } } /** * 形狀工廠類 */ class FactoryShape { publicstatic functioncreate() { switch (func_num_args()) { case1: return newCircle(func_get_arg(0)); case2: return newRectangle(func_get_arg(0), func_get_arg(1)); default: # code... break; } } } $rect =FactoryShape::create(5, 5); // object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) } var_dump($rect); echo "<br>"; // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) } $circle =FactoryShape::create(4); var_dump($circle);
觀察者設計模式
觀察者模式是挺常見的一種設計模式,使用得當會給程序帶來非常大的便利,使用得不當,會給後來人一種難以維護的想法。
什麼是觀察者模式?一個對象通過提供方法允許另一個對象即觀察者 注冊自己)使本身變得可觀察。當可觀察的對象更改時,它會將消息發送到已注冊的觀察者。這些觀察者使用該信息執行的操作與可觀察的對象無關。結果是對象可以相互對話,而不必了解原因。觀察者模式是一種事件系統,意味著這一模式允許某個類觀察另一個類的狀態,當被觀察的類狀態發生改變的時候,觀察類可以收到通知並且做出相應的動作;觀察者模式為您提供了避免組件之間緊密耦。看下面例子你就明白了!
<?php /* 觀察者接口 */ interfaceInterfaceObserver { functiononListen($sender, $args); functiongetObserverName(); } // 可被觀察者接口 interfaceInterfaceObservable { functionaddObserver($observer); functionremoveObserver($observer_name); } // 觀察者抽象類 abstractclass Observer implementsInterfaceObserver { protected $observer_name; functiongetObserverName() { return $this->observer_name; } functiononListen($sender, $args) { } } // 可被觀察類 abstractclass Observable implementsInterfaceObservable { protected $observers = array(); publicfunctionaddObserver($observer) { if ($observerinstanceofInterfaceObserver) { $this->observers[] = $observer; } } publicfunctionremoveObserver($observer_name) { foreach ($this->observersas $index => $observer) { if ($observer->getObserverName() === $observer_name) { array_splice($this->observers, $index, 1); return; } } } } // 模擬一個可以被觀察的類 class A extendsObservable { publicfunctionaddListener($listener) { foreach ($this->observersas $observer) { $observer->onListen($this, $listener); } } } // 模擬一個觀察者類 class B extendsObserver { protected $observer_name = 'B'; publicfunctiononListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } // 模擬另外一個觀察者類 class C extendsObserver { protected $observer_name = 'C'; publicfunctiononListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } $a = new A(); // 注入觀察者 $a->addObserver(new B()); $a->addObserver(new C()); // 可以看到觀察到的信息 $a->addListener('D'); // 移除觀察者 $a->removeObserver('B'); // 打印的信息: // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D" // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D"
小結
初入PHP的世界,目前只了解這些基本的設計模式,慢慢學著去應用!如果文中有不對之處,請在評論中指出,我會在明確之後更正文章內容!