PHP设计模式单例模式的继承实现

最近在做O2O平台的接入,因为发现之前公司的代码里已经有了某家开放平台的接入代码,如果我再往原先的控制器上加入逻辑代码,整个控制器的耦合度会非常高。加上每个平台有自己的签名验证算法,把加解密的方法写到平台的接入控制器里固然好,但是还是有耦合度问题。因此我的做法是先实现目前手上需要的功能,稍后会用面向对象的方法写一个抽象类,然后用对应平台的子类实现相应平台所需要的业务逻辑代码。

在写的过程中,发现现在框架中使用的YiiMongoDbSuite为模型类实现的一个单例模式很有意思,遂决定使用同样的写法实现我所需要的平台接入类。在这里我将这种写法略微总结一下。为了方便,例子中的变量名都使用YiiMongoDbSuite拓展中的变量名了。

  1. 父类(抽象类)中定义一个私有的静态变量$_model,类型为数组,用来保存子类实例化后的结果。

  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";
    }

}

测试代码

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

// 尝试用同样的方法生成一个实例并打印
var_dump(Chils::model());
// 直接用new关键字生成一个实例并打印
var_dump(new Child());

结果

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()这样的方式实例化子类。

posted on 2015-11-05 00:25  粥煦尘  阅读(1391)  评论(0编辑  收藏  举报

导航