7

我有一个小问题。这里是:

  1. 这是我的单例抽象类:

    abstract class Singleton {
    
    protected static $_instance = NULL;
    
    /**
     * Prevent direct object creation
     */
    final private function  __construct()
    {
        $this->actionBeforeInstantiate();
    }
    
    /**
     * Prevent object cloning
     */
    final private function  __clone() { }
    
    /**
     * Returns new or existing Singleton instance
     * @return Singleton
     */
    final public static function getInstance(){
    
        if(null !== static::$_instance){
            return static::$_instance;
        }
        static::$_instance = new static();
        return static::$_instance;
    }
    
    abstract protected function  actionBeforeInstantiate();
    
    }
    
  2. 之后,我创建了一个抽象注册表类:

    abstract class BaseRegistry extends Singleton
    {
        //...
    }
    
  3. 现在是会话注册的时候了。

    class BaseSessionRegistry extends BaseRegistry
    {
    
    //...
    
    protected function actionBeforeInstantiate()
    {
        session_start();
    }
    
    }
    
  4. 最后一步:

    class AppBaseSessionRegistryTwo extends BaseSessionRegistry { //... }
    
    class AppBaseSessionRegistry extends BaseSessionRegistry { //... }
    
  5. 测试

    $registry = AppBaseSessionRegistry::getInstance();
    $registry2 =AppBaseSessionRegistryTwo::getInstance();
    
    echo get_class($registry) . '|' . get_class($registry2) . '<br>';
    

输出:

AppBaseSessionRegistry|AppBaseSessionRegistry

我的期望是:

AppBaseSessionRegistry|AppBaseSessionRegistryTwo

为什么我会得到这样的结果?我怎样才能重新编写我的代码以获得我期望的结果?

更新:我在我的框架中使用它。用户将扩展我的BaseSessionRegistry课程并添加他们的东西。我想在我的框架类中解决这个问题

4

3 回答 3

4

你需要这样做:

class AppBaseSessionRegistryTwo extends BaseSessionRegistry {
    protected static $_instance = NULL;
    // ...
}

class AppBaseSessionRegistry extends BaseSessionRegistry { 
    protected static $_instance = NULL;
    //... 
}

如果您不单独声明静态属性,它们将共享其父级的相同静态属性。

更新: 如果您不希望孩子声明静态属性,那么您可以将静态属性声明为父数组。

abstract class Singleton {

  protected static $_instances = array();

  // ...
  /**
   * Returns new or existing Singleton instance
   * @return Singleton
   */
  final public static function getInstance(){
    $class_name = get_called_class();
    if(isset(self::$_instances[$class_name])){
        return self::$_instances[$class_name];
    }
        return self::$_instances[$class_name] = new static();
    }

   abstract protected function  actionBeforeInstantiate();

}
于 2012-09-08T10:27:09.513 回答
1

你的第一行:

$registry = AppBaseSessionRegistry::getInstance();

将填充protected static $_instance一个AppBaseSessionRegistry实例。在您的下一行$registry2 =AppBaseSessionRegistryTwo::getInstance();,受保护的静态 $_instance 已经有一个值,并且该实例将被返回。

一般来说,单例和静态是邪恶的。将它们结合在一起是可怕的。从事良好的 OO 编程业务,避免单例和静态。

于 2012-09-08T10:30:08.580 回答
1
 $registry = AppBaseSessionRegistry::getInstance();

上面的语句将 $_instance 设置为 AppBaseSessionRegistry 类的对象,
因为在 getInstance 方法中,我们正在检查它是否先前已设置,然后返回该值,因此为您的第二条语句

$registry2 =AppBaseSessionRegistryTwo::getInstance();

getInstance 将返回 AppBaseSessionRegistry 类的对象,即 $registry1 和 registry 2 引用同一个对象

于 2012-09-08T10:44:16.333 回答