PHP面向对象笔记 —— 125 单例模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dyw_666666/article/details/79968664

// 如何限制多人开发时只得到一个对象?

// 单例模式常用也常考,注意练习

/*
第一步:

一个普通类放在这,就可以new 来实例化,
也可new多次 得到多个对象

就不是单例了.
*/

/*
第二步:

那么如何不让类new呢?

我们用构造方法 保护/私有化
外部就不能new了

然而,不能new就得不到对象,
又不是单例了,是没例.
*/

class single { 
    protected function __construct() {

    }

    public function getInstance() {
        return new self();
    }
}

$s1 = new single(); //报错

/*
Fatal error: Call to protected single::__construct() from invalid context 
报错:你在调用一个受保护的construct
*/

/*
第三步:

我们可以通过内部的static方法来调用.

static不依赖于对象,所以可以直接调用.
*/

class single2 {
    public $hash; // public 一个随机码

    protected function __construct() {
        $this->hash = mt_rand(1,99999);
    }

    static public function getInstance() {
        return new self();
    }
}

$s1 = single2::getInstance();
$s2 = single2::getInstance();
/*
两个对象什么时间相等?
只有指向同一个对象的地址的时候,才相等.
*/

print_r($s1);
print_r($s2);


if($s1 == $s2) {
    echo '是一个对象';
} else {
    echo '不是一个对象';
}
/*
single2 Object
(
    [hash] => 42633
)
single2 Object
(
    [hash] => 95744
)
不是一个对象
*/

echo '<hr >';

/*
第四步:

通过内部的static方法实例化.
并把实例保存在类内部的静态属性上.
*/

class single3 {
    public $hash; // public 一个随机码

    static protected $ins = null;

    protected function __construct() {
        $this->hash = mt_rand(1,99999);
    }

    static public function getInstance() {
        if(self::$ins instanceof self) {
        // instance示例 of谁的
        // 专门判断某个对象是不是某个类的实例 用的     
            return self::$ins;

        }

        self::$ins = new self();
        return self::$ins;
    }
}

$s1 = single3::getInstance();
$s2 = single3::getInstance();


print_r($s1);
print_r($s2);


if($s1 == $s2) {
    echo '是一个对象';
} else {
    echo '不是一个对象';
}
/*
single3 Object
(
    [hash] => 11410
)
single3 Object
(
    [hash] => 11410
)
是一个对象
*/

// ============看问题============ //
/*
我们的目的是让其成为同一个对象,
然而此时继承过来的改写后还能否是同一个对象?
*/

class test extends single3 {
    public function __construct() {
        parent::__construct();
    }
}

$t1 = new test();
$t2 = new test();


print_r($t1);
print_r($t2);


if($t1 == $t2) {
    echo '是一个对象';
} else {
    echo '不是一个对象';
}
/*
test Object
(
    [hash] => 99116
)
test Object
(
    [hash] => 19702
)
不是一个对象
*/


// ============解决问题============ //
/*
我们写出的单例继承了一下就不灵了,那么如何解决呢?
答:可以用final.

在PHP中,final 可以修改类,方法名,但不能修改属性.

在Java中,final 可以修改属性,此时属性值,就是一个常量,不可修改.
*/

// final修改方法,此方法不影响继承,但是此方法不允许重写.

/*
final class Human {

}

class Stu extends Human {

}

报错如下:不能继承自最终的类
Fatal error: Class Stu may not inherit from final class (Human) 
*/


class Human {
    final public function say() {
        echo '华夏子孙';
    }

    public function show() {
        echo '哈哈';
    }
}


class Stu extends Human {

}

$ming = new Stu;
$ming->say();


/*
class FreshMan extends Stu {
    public function say() {
        echo '我要出国';
    }
}

报错如下:不能覆盖父类原有的say方法
Fatal error: Cannot override final method Human::say() 
*/

/*
第五步:

运用final
解决被继承后单例就失灵的问题.
*/

class single4 {
    public $hash; // public 一个随机码

    static protected $ins = null;

    final protected function __construct() {
        $this->hash = mt_rand(1,99999);
    }

    static public function getInstance() {
        if(self::$ins instanceof self) {
        // instance示例 of谁的
        // 专门判断某个对象是不是某个类的实例 用的     
            return self::$ins;

        }

        self::$ins = new self();
        return self::$ins;
    }
}


/*
class test extends single4 {
    public function __construct() {
        parent::__construct();
    }
}

$t1 = new test();
$t2 = new test();

报错如下:不能覆盖父类single4原有的__construct方法
Fatal error: Cannot override final method single4::__construct()
*/


class test2 extends single4 {

}

$t1 = test2::getInstance();
$t2 = test2::getInstance();


print_r($t1);
print_r($t2);


if($t1 == $t2) {
    echo '是一个对象';
} else {
    echo '不是一个对象';
}
/*
single4 Object
(
    [hash] => 44041
)
single4 Object
(
    [hash] => 44041
)
是一个对象
*/

// ======clone魔术方法======

$t3 = clone $t2;

if($t3 == $t2) {
    echo '是一个对象<br >';
} else {
    echo '不是一个对象<br >';
} // 是一个对象


if($t3 === $t2) {
    echo '是一个对象<br >';
} else {
    echo '不是一个对象<br >';
} // 不是一个对象

// 此时我们发现即使是克隆过来的,在严格相等情况下,也不是一个对象

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页