設計模式是一套被反復使用仔蝌,代碼設計經(jīng)驗的總結泛领,它的主要作用是提升代碼的復用性、擴展性和可靠性敛惊,本文主要介紹常見的幾種設計模式:工廠模式渊鞋、單例模式、觀察者模式瞧挤、策略模式锡宋。
1.工廠模式:
工廠模式是創(chuàng)建型設計模式,它的實現(xiàn)方式是:定義抽象接口特恬,根據(jù)產(chǎn)品類具體實現(xiàn)接口执俩,通過工廠類管理具體產(chǎn)品的對象創(chuàng)建;體現(xiàn)的原則是面向接口編程鸵鸥,而不是面向?qū)崿F(xiàn)編程奠滑,這樣可以提高代碼的擴展性丹皱。下面舉例分析妒穴。
1.1.不使用工廠模式
class Cal
{
public function calculate($a, $b, $operator)
{
switch ($operator) {
case '+':
$result = $a + $b;
break;
case '-':
$result = $a - $b;
break;
case '*':
$result = $a * $b;
break;
default:
$result = $a + $b;
}
return $result;
}
}
這種方式看起來沒有問題,但是程序的擴展性并不好:假如要加很多個其他計算功能(開方摊崭、乘方讼油、對數(shù)、三角函數(shù)等)呢簸,則只能在case中繼續(xù)堆砌代碼矮台,這么做的壞處是所有計算類都高度耦合在一起,如果新加的若干個計算類中有一處代碼出現(xiàn)問題根时,則其他計算類都無法使用瘦赫,同時程序的執(zhí)行效率也大大降低。
2.1.使用工廠模式
為了解決上述問題蛤迎,降低各個具體類(以計算類為例)的耦合性确虱,提升程序的可擴展性,工廠模式就應運而生替裆,示例代碼如下:
//1.計算類的抽象接口
interface CalC
{
public function getTwoVal($a, $b);
}
//2.面向接口編程校辩,通過實現(xiàn)接口來擴展具體的功能類
class AddC implements CalC
{
public function getTwoVal($a, $b)
{
return $a + $b;
}
}
class SubC implements CalC
{
public function getTwoVal($a, $b)
{
return $a - $b;
}
}
class MultiplyC implements CalC
{
public function getTwoVal($a, $b)
{
return $a * $b;
}
}
//3.工廠類管理具體計算類的創(chuàng)建
class Factory
{
public static function getObj($operator)
{
switch ($operator) {
case '+':
$cal = new AddC();
break;
case '-':
$cal = new SubC();
break;
case '*':
$cal = new MultiplyC();
break;
default:
$cal = new AddC();
}
return $cal;
}
}
//使用
$add = Factory::getObj('+');
$res = $add->getTwoVal(5, 2);
echo $res;
通過上述代碼可以看到,各個具體計算類的只有自己的相關代碼而不包含其他代碼辆童,計算類間的耦合性大大降低宜咒,利于整個計算功能的擴展。
2.單例模式:
單例模式應該是最簡單的設計模式了把鉴,同時也非常常見故黑,它的核心思想是只實例化一個對象供全局使用,從而減少內(nèi)存開銷、節(jié)省系統(tǒng)資源倍阐。
代碼示例:
//2.單例模式概疆,三私一公兩靜態(tài)
class Db
{
private static $instance;
private function __construct()
{
//內(nèi)部初始化
}
private function __clone()
{
//禁止克隆
}
//開放單一入口
public static function getDb()
{
//判斷實例是否已存在
if (!(self::$instance instanceof self)) {
self::$instance = new Db();
}
return self::$instance;
}
}
//測試單例
$db = Db::getDb();
$db1 = Db::getDb();
$res = ($db === $db1);
var_dump($res);
3.觀察者模式:
觀察者模式屬于行為型設計模式,常用于存在一對多關系時:當一個對象發(fā)生變更操作時峰搪,會自動通知其依賴對象惜论。具體實現(xiàn)方式:將一個類設置為可被觀察(實現(xiàn)接口),接著它可以注冊觀察者類(實現(xiàn)觀察者類接口)属提,當前類發(fā)生操作變化時可通知觀察者類西采。從而實現(xiàn)觀察和被觀察者業(yè)務邏輯的松散耦合。
代碼示例
interface Observer
{
//觀察者的方法
function onChanges($sender, $args);
}
interface Observable
{
//注冊觀察者
function addObserver($observer);
}
class UserList implements Observable
{
private $observers;
//可觀察的類鞠柄,添加其觀察者
public function addObserver($observer)
{
$this->observers[] = $observer;
}
//執(zhí)行方法侦高,并通知觀察者
public function addCustomer($name)
{
foreach ($this->observers as $observer) {
$observer->onChanges($this, $name);//通知觀察者,傳遞參數(shù)和發(fā)送人信息
}
}
}
class UserListLogger implements Observer
{
//觀察者接受參數(shù)厌杜,并執(zhí)行操作
function onChanges($sender, $args)
{
echo "add {$args} to user_list" . PHP_EOL;
}
}
//使用
$logger = new UserListLogger();//觀察類
$userList = new UserList();//可觀察類
$userList->addObserver($logger);//添加觀察類
$userList->addCustomer('Bryan');//執(zhí)行動作
觀察者的使用場景很多奉呛,比如用戶注冊后發(fā)送郵件通知管理員和用戶,我們可以將注冊邏輯寫到可觀察類函數(shù)中夯尽,將發(fā)送郵件寫到觀察者類函數(shù)中瞧壮,這樣的好處是將發(fā)送郵件邏輯和注冊邏輯實現(xiàn)松散耦合,注冊邏輯的修改不會影響發(fā)送郵件邏輯匙握。再比如咆槽,用戶下單購買商品時,可以在下單成功后通知其觀察者圈纺,各個觀察者分別實現(xiàn)購買記錄寫入日志秦忿、發(fā)送短信、送兌換券積分等業(yè)務邏輯蛾娶。
4.策略模式
策略模式是行為型設計模式灯谣,它可以將一個類的行為方法在運行時進行更改,避免大量使用if-else語句帶來的復雜度以及維護成本蛔琅。
代碼示例
interface CalStrategy
{
function getVal($a, $b);
}
class AddStrategy implements CalStrategy
{
function getVal($a, $b)
{
return $a + $b;
}
}
class SubStrategy implements CalStrategy
{
function getVal($a, $b)
{
return $a - $b;
}
}
class MultiplyStrategy implements CalStrategy
{
function getVal($a, $b)
{
return $a * $b;
}
}
class CalContext
{
private $strategy;
//初始化策略
public function __construct(CalStrategy $strategy)
{
$this->strategy = $strategy;
}
//用于策略變更
public function setStrategy(CalStrategy $strategy)
{
$this->strategy = $strategy;
}
public function getVal($a, $b)
{
return $this->strategy->getVal($a, $b);
}
}
//使用
$calContext = new CalContext(new AddStrategy());//初始化策略
$addResult = $calContext->getVal(5, 10);
echo $addResult . PHP_EOL;
$calContext->setStrategy(new MultiplyStrategy());//變更策略
$mulResult = $calContext->getVal(5, 10);
echo $mulResult . PHP_EOL;
上述代碼的例子仍然是工廠設計模式的例子-計算類胎许。可以看到揍愁,工廠模式和策略模式都可以實現(xiàn)這種功能呐萨,區(qū)別在于:工廠模式是類的統(tǒng)一管理,關注的是實例的創(chuàng)建莽囤,屬于創(chuàng)建型設計模式谬擦;而策略模式接受已經(jīng)創(chuàng)建好的實例,實現(xiàn)不同的行為(變更策略)朽缎,屬于行為型設計模式惨远。