PHP設計模式單例模式的繼承實現

最近在作O2O平臺的接入,由於發現以前公司的代碼裏已經有了某家開放平臺的接入代碼,若是我再往原先的控制器上加入邏輯代碼,整個控制器的耦合度會很是高。加上每一個平臺有本身的簽名驗證算法,把加解密的方法寫到平臺的接入控制器裏當然好,可是仍是有耦合度問題。所以個人作法是先實現目前手上須要的功能,稍後會用面向對象的方法寫一個抽象類,而後用對應平臺的子類實現相應平臺所須要的業務邏輯代碼。javascript

在寫的過程當中,發現如今框架中使用的YiiMongoDbSuite爲模型類實現的一個單例模式頗有意思,遂決定使用一樣的寫法實現我所須要的平臺接入類。在這裏我將這種寫法略微總結一下。爲了方便,例子中的變量名都使用YiiMongoDbSuite拓展中的變量名了。php

  1. 父類(抽象類)中定義一個私有的靜態變量$_model,類型爲數組,用來保存子類實例化後的結果。java

  2. 父類實現一個靜態的公共函數model(),用於生成子類的實例化並保存在$_model,傳參爲類名__CLASS__算法

  3. 子類中一樣實現靜態公共函數model(),直接返回繼承的父類的model()方法結果。數組

具體仍是看實現的代碼。框架

父類(抽象類)函數

<?php 
abstract class Father {

    public function __construct() {}

    private static $_models = array();

    public static function model($className = __CLASS__) {
        if (isset(self::$_models[$className])) {
            return self::$_models[$className];
        } else {
            $model = self::$_models[$className] = new $className(null);
            return $model;
        }
    }

}

子類測試

<?php
class Child extends Father {

    public static function model($className=__CLASS__) {
        return parent::model($className);
    }

    public function test() {
        echo 'i am child!'."\n";
    }

}

測試代碼ui

<?php
var_dump(Child::model());
Child::model()->test();

// 嘗試用一樣的方法生成一個實例並打印
var_dump(Chils::model());
// 直接用new關鍵字生成一個實例並打印
var_dump(new Child());

結果code

object(Putao)#1 (0) {}
i am child!
object(Putao)#1 (0) {}
object(Putao)#2 (0) {}

能夠注意到,使用Child::model()生成的實例ID相同,而直接經過new Child()生成的實例ID爲2。

固然,也能夠把父類的__constract()方法改成私有方法,這樣new關鍵字就失效了,只能經過Child::model()這樣的方式實例化子類。

相關文章
相關標籤/搜索