PHP常用的三種設(shè)計(jì)模式匯總
本篇文章是學(xué)習(xí)PHP中常用的三種設(shè)計(jì)模式的筆記及總結(jié),不管采用哪一門語言開發(fā)什么,幾乎都會(huì)使用到設(shè)計(jì)模式,我們?yōu)槭裁葱枰O(shè)計(jì)模式呢?它的誕生對(duì)于我們開發(fā)人員來說有什么樣的作用與意義呢?
相信做iOS開發(fā)的人員對(duì)設(shè)計(jì)模式也會(huì)挺熟悉吧?比如單例設(shè)計(jì)模式、工廠設(shè)計(jì)模式、觀察者模式、MVC框架結(jié)構(gòu)設(shè)計(jì)模式等。
接下來我們一起來學(xué)習(xí)PHP中最常用的三種設(shè)計(jì)模式:?jiǎn)卫O(shè)計(jì)模式、工廠設(shè)計(jì)模式和觀察者設(shè)計(jì)模式。
單例設(shè)計(jì)模式
所謂單例模式,即在應(yīng)用程序中最多只有該類的一個(gè)實(shí)例存在,一旦創(chuàng)建,就會(huì)一直存在于內(nèi)存中!
單例設(shè)計(jì)模式常應(yīng)用于數(shù)據(jù)庫類設(shè)計(jì),采用單例模式,只連接一次數(shù)據(jù)庫,防止打開多個(gè)數(shù)據(jù)庫連接。
一個(gè)單例類應(yīng)具備以下特點(diǎn):
單例類不能直接實(shí)例化創(chuàng)建,而是只能由類本身實(shí)例化。因此,要獲得這樣的限制效果,構(gòu)造函數(shù)必須標(biāo)記為private,從而防止類被實(shí)例化。
需要一個(gè)私有靜態(tài)成員變量來保存類實(shí)例和公開一個(gè)能訪問到實(shí)例的公開靜態(tài)方法。
在PHP中,為了防止他人對(duì)單例類實(shí)例克隆,通常還為其提供一個(gè)空的私有__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);
工廠設(shè)計(jì)模式
工廠設(shè)計(jì)模式常用于根據(jù)輸入?yún)?shù)的不同或者應(yīng)用程序配置的不同來創(chuàng)建一種專門用來實(shí)例化并返回其對(duì)應(yīng)的類的實(shí)例。
我們舉例子,假設(shè)矩形、圓都有同樣的一個(gè)方法,那么我們用基類提供的API來創(chuàng)建實(shí)例時(shí),通過傳參數(shù)來自動(dòng)創(chuàng)建對(duì)應(yīng)的類的實(shí)例,他們都有獲取周長和面積的功能。
<?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);
觀察者設(shè)計(jì)模式
觀察者模式是挺常見的一種設(shè)計(jì)模式,使用得當(dāng)會(huì)給程序帶來非常大的便利,使用得不當(dāng),會(huì)給后來人一種難以維護(hù)的想法。
什么是觀察者模式?一個(gè)對(duì)象通過提供方法允許另一個(gè)對(duì)象即觀察者 注冊(cè)自己)使本身變得可觀察。當(dāng)可觀察的對(duì)象更改時(shí),它會(huì)將消息發(fā)送到已注冊(cè)的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對(duì)象無關(guān)。結(jié)果是對(duì)象可以相互對(duì)話,而不必了解原因。觀察者模式是一種事件系統(tǒng),意味著這一模式允許某個(gè)類觀察另一個(gè)類的狀態(tài),當(dāng)被觀察的類狀態(tài)發(fā)生改變的時(shí)候,觀察類可以收到通知并且做出相應(yīng)的動(dòng)作;觀察者模式為您提供了避免組件之間緊密耦??聪旅胬幽憔兔靼琢耍?/p>
<?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; } } } } // 模擬一個(gè)可以被觀察的類 class A extendsObservable { publicfunctionaddListener($listener) { foreach ($this->observersas $observer) { $observer->onListen($this, $listener); } } } // 模擬一個(gè)觀察者類 class B extendsObserver { protected $observer_name = 'B'; publicfunctiononListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } // 模擬另外一個(gè)觀察者類 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"
小結(jié)
初入PHP的世界,目前只了解這些基本的設(shè)計(jì)模式,慢慢學(xué)著去應(yīng)用!如果文中有不對(duì)之處,請(qǐng)?jiān)谠u(píng)論中指出,我會(huì)在明確之后更正文章內(nèi)容!
相關(guān)文章
php使用fputcsv實(shí)現(xiàn)大數(shù)據(jù)的導(dǎo)出操作詳解
這篇文章主要介紹了php使用fputcsv實(shí)現(xiàn)大數(shù)據(jù)的導(dǎo)出操作,結(jié)合實(shí)例形式詳細(xì)分析了PHP百萬級(jí)數(shù)據(jù)的插入以及使用fputcsv進(jìn)行大數(shù)據(jù)的導(dǎo)出相關(guān)操作技巧,需要的朋友可以參考下2020-02-02PHP數(shù)組與字符串互相轉(zhuǎn)換實(shí)例
在本篇文章里小編給大家分享的是關(guān)于PHP數(shù)組與字符串互相轉(zhuǎn)換實(shí)例內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2020-05-05PHP實(shí)現(xiàn)對(duì)數(shù)字分隔加千分號(hào)的方法
今天小編就為大家分享一篇關(guān)于PHP實(shí)現(xiàn)對(duì)數(shù)字分隔加千分號(hào)的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03php判斷兩個(gè)浮點(diǎn)數(shù)是否相等的方法
這篇文章主要介紹了php判斷兩個(gè)浮點(diǎn)數(shù)是否相等的方法,涉及php操作浮點(diǎn)數(shù)的技巧,比較實(shí)用,需要的朋友可以參考下2015-03-03php設(shè)計(jì)模式 Bridge (橋接模式)
將抽象部份與它實(shí)現(xiàn)部分分離,使用它們都可以有獨(dú)立的變化2011-06-06php使用file函數(shù)、fseek函數(shù)讀取大文件效率對(duì)比分析
這篇文章主要對(duì)比分析了php使用file函數(shù)、fseek函數(shù)讀取大文件的效率,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11