<?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?

解决方案 »

  1.   

    是private function __clone吧,单例的释放也不应该是析构函数做的,概念完全混淆了,应该提供独立的public static接口来释放单例对象。1,同一个对象
    2,上边已经说了,不会变成null的,你不应该再使用那两个变量了,因为对象是引用。
      

  2.   

    你可以看PHP 手册 原文:http://www.php.net/manual/zh/language.oop5.patterns.php我除了加了一个 destroy() 以外没做任何改动
      

  3.   

    写了个小测试
    <?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)
    */现在回复你的问题
    $test 和 $b 都指向 Example::singleton() 这个生成的对象?
    是,PHP5对象是引用传递的,所以才会提供克隆这个功能。可以看到第3,4条的 refcount() 引用计数为什么我 的 destroy() 方法会出错?
    静态类成员变量不允许销毁,从程序开始到结束会一直存在
      

  4.   

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

  5.   

    你在 destroy() 方法中 unset(self::$instance); 这是不允许的
    因为静态属性时所有这个类的实例所共有的,可以对他赋值,而不可以删除。因为删除了就将影响到其他实例的正常工作