【設計模式】之工廠模式晌梨、單例模式桥嗤、觀察者模式、策略模式(PHP)

設計模式是一套被反復使用仔蝌,代碼設計經(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)不同的行為(變更策略)朽缎,屬于行為型設計模式惨远。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谜悟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子北秽,更是在濱河造成了極大的恐慌葡幸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贺氓,死亡現(xiàn)場離奇詭異蔚叨,居然都是意外死亡,警方通過查閱死者的電腦和手機辙培,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門蔑水,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扬蕊,你說我怎么就攤上這事搀别。” “怎么了尾抑?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵歇父,是天一觀的道長。 經(jīng)常有香客問我再愈,道長榜苫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任践磅,我火速辦了婚禮单刁,結果婚禮上灸异,老公的妹妹穿的比我還像新娘府适。我一直安慰自己,他們只是感情好肺樟,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布檐春。 她就那樣靜靜地躺著,像睡著了一般么伯。 火紅的嫁衣襯著肌膚如雪疟暖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天田柔,我揣著相機與錄音俐巴,去河邊找鬼。 笑死硬爆,一個胖子當著我的面吹牛欣舵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缀磕,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缘圈,長吁一口氣:“原來是場噩夢啊……” “哼劣光!你這毒婦竟也來了?” 一聲冷哼從身側響起糟把,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绢涡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后遣疯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雄可,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年缠犀,在試婚紗的時候發(fā)現(xiàn)自己被綠了滞项。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡夭坪,死狀恐怖文判,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情室梅,我是刑警寧澤戏仓,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站亡鼠,受9級特大地震影響赏殃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜间涵,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一仁热、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勾哩,春花似錦抗蠢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至潜叛,卻和暖如春秽褒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背威兜。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工销斟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椒舵。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓蚂踊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逮栅。 傳聞我的和親對象是個殘疾皇子悴势,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容