PHP常用的三種設(shè)計(jì)模式匯總
本篇文章是學(xué)習(xí)PHP中常用的三種設(shè)計(jì)模式的筆記及總結(jié),不管采用哪一門語言開發(fā)什么,幾乎都會(huì)使用到設(shè)計(jì)模式,我們?yōu)槭裁葱枰O(shè)計(jì)模式呢?它的誕生對于我們開發(fā)人員來說有什么樣的作用與意義呢?
相信做iOS開發(fā)的人員對設(shè)計(jì)模式也會(huì)挺熟悉吧?比如單例設(shè)計(jì)模式、工廠設(shè)計(jì)模式、觀察者模式、MVC框架結(jié)構(gòu)設(shè)計(jì)模式等。
接下來我們一起來學(xué)習(xí)PHP中最常用的三種設(shè)計(jì)模式:單例設(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中,為了防止他人對單例類實(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í)例化并返回其對應(yīng)的類的實(shí)例。
我們舉例子,假設(shè)矩形、圓都有同樣的一個(gè)方法,那么我們用基類提供的API來創(chuàng)建實(shí)例時(shí),通過傳參數(shù)來自動(dòng)創(chuàng)建對應(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è)對象通過提供方法允許另一個(gè)對象即觀察者 注冊自己)使本身變得可觀察。當(dāng)可觀察的對象更改時(shí),它會(huì)將消息發(fā)送到已注冊的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對象無關(guān)。結(jié)果是對象可以相互對話,而不必了解原因。觀察者模式是一種事件系統(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)用!如果文中有不對之處,請?jiān)谠u論中指出,我會(huì)在明確之后更正文章內(nèi)容!
相關(guān)文章
PHP實(shí)現(xiàn)順時(shí)針打印矩陣(螺旋矩陣)的方法示例
這篇文章主要介紹了PHP實(shí)現(xiàn)順時(shí)針打印矩陣(螺旋矩陣)的方法,涉及PHP基于數(shù)組遍歷、運(yùn)算模擬打印實(shí)現(xiàn)螺旋矩陣功能的相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
PHP實(shí)現(xiàn)的多維數(shù)組去重操作示例
這篇文章主要介紹了PHP實(shí)現(xiàn)的多維數(shù)組去重操作,結(jié)合實(shí)例形式分析了php序列化json字符串及數(shù)組轉(zhuǎn)換、去重等相關(guān)操作技巧,需要的朋友可以參考下2018-07-07
php通過pecl方式安裝擴(kuò)展的實(shí)例講解
下面小編就為大家分享一篇php通過pecl方式安裝擴(kuò)展的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02
php文件后綴不強(qiáng)制為.php的實(shí)操方法
在本篇文章里小編給大家整理的是一篇關(guān)于php文件后綴不強(qiáng)制為.php的實(shí)操方法,有需要的朋友們參考下。2019-09-09
PHP錯(cuò)誤提示It is not safe to rely on the system……的解決方法
今天小編就為大家分享一篇關(guān)于PHP錯(cuò)誤提示It is not safe to rely on the system……的解決方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03

