日期:2014-05-17  浏览次数:20465 次

基础编程:关于单例模式的问题,大牛进来撸~~~
<?php
class Example
{
  // 保存类实例在此属性中
  private static $instance;
   
  // 构造方法声明为private,防止直接创建对象
  private function __construct() 
  {
  echo 'I am constructed<br>';
  }

  // singleton 方法
  public static function singleton() 
  {
  if(!isset(self::$instance))
{
$c=__CLASS__;
self::$instance=new $c; 
}

  return self::$instance;
  }


   
  // Example类中的普通方法
  public function bark()
  {
  echo 'Woof!';
  }

  // 阻止用户复制对象实例
  public function __clone()
  {
  trigger_error('Clone is not allowed.', E_USER_ERROR);
  }

public function destroy()
{
unset(self::$instance);
}

}


// 这个写法会出错,因为构造方法被声明为private
//$test = new Example;


// 下面将得到Example类的单例对象
$test = Example::singleton();
$test->bark();

// 复制对象将导致一个E_USER_ERROR.
//$test_clone = clone $test;


$b=Example::singleton();

$b->destroy();

?>


原文:http://www.php.net/manual/zh/language.oop5.patterns.php


这里我想问:

1) $b=Example::singleton(); 是生成一个新的对象 ,还是

$test 和 $b 都指向 Example::singleton() 这个生成的对象?


2) 为什么我 的 destroy() 方法会出错?有没什么办法可以销毁 Example::singleton() 这个对象或说令它变成null,

是不是这样就使得 $test 和 $b 同时变成了 null?



------解决方案--------------------
是private function __clone吧,单例的释放也不应该是析构函数做的,概念完全混淆了,应该提供独立的public static接口来释放单例对象。

1,同一个对象
2,上边已经说了,不会变成null的,你不应该再使用那两个变量了,因为对象是引用。
------解决方案--------------------
写了个小测试
PHP code
<?php
class hello
{
public static $i;

public static function getI()
{
    if( ! self::$i instanceof self){
        self::$i = new self;
    }
    // 输出变量的一些信息
    debug_zval_dump(self::$i);
    // 你可以先注释掉这句
    self::$i = null;
    debug_zval_dump(self::$i);
    return self::$i;
}
private function __construct(){}
private function __clone(){}

}

$i = hello::getI();

debug_zval_dump($i);
debug_zval_dump(hello::$i);

/**
output:
// 1
object(hello)#1 (0) refcount(2){ 
}
// 2th
NULL refcount(2)
// 3, 4
NULL refcount(3)
NULL refcount(3)
*/

------解决方案--------------------
自己也试了一下,一个对象自身一个引用,变量再引用就是2个引用,所以null和一开始的$i是这样情况,不知道对不对,不过对不对也不重要了。


------解决方案--------------------
探讨
2) 为什么我 的 destroy() 方法会出错?有没什么办法可以销毁 Example::singleton() 这个对象或说令它变成null,