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

原创 2018年04月16日 23:49:05

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

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

/*
第一步:

一个普通类放在这,就可以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 >';
} // 不是一个对象

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

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

PHP面向对象-单列模式

单例模式,在PHP面向对象中应用的比较广泛, 通常为了节省资源,在性能方面上,代码重用性上考虑,使用设计模式是很不错的选择, 比如数据库操作类系统类库等,通常开源代码都会使用单列模式去设计完成,使用单...
  • xueling022
  • xueling022
  • 2015-06-13 18:24:29
  • 634

php面向对象(工厂模式与单例模式)

今天刚学习了php的设计模式,一个是工厂模式而另一个是单例模式,工厂模式设计出来就是为了一种方便创建对象而做出来的。还有一个是单例模式,单例模式的设计有些比较难以理解,我们必须一步一步的分析:单例类的...
  • peterjiajia
  • peterjiajia
  • 2015-11-11 14:42:13
  • 719

php面向对象之单例模式--125

转自:燕十八
  • jasonkent27
  • jasonkent27
  • 2014-08-18 21:52:27
  • 314

面向对象—单例模式

设计模式:解决某一类问题行之有效的解决办法(思想)。 单例(Singleton)设计模式: 学习设计模式必须先弄清楚它是解决什么问题的。 单例是解决什么问题的呢? 可以保证一个类的对象唯一性。...
  • John_boom
  • John_boom
  • 2017-04-26 15:16:54
  • 423

燕十八PHP培训笔记

  • 2015年03月22日 22:26
  • 2.66MB
  • 下载

PHP中OOP面向对象笔记

PHP的面向对象: ===================================================     对象是客观存在的一个实体。     类是对对象抽象的一个描述。...
  • xiaoxiaohui520134
  • xiaoxiaohui520134
  • 2016-07-18 17:51:56
  • 320

PHP面向对象基础笔记三

抽象方法以及多态 一. 什么是抽象方法 1.定义:一个方法如果没有方法体,则这个方法就是抽象方法。 2.声明一个方法,不使用{},而直接分号结束 如果是抽象方法,必须使用abstract(...
  • u012675743
  • u012675743
  • 2015-03-24 17:27:12
  • 391

PHP面向对象笔记(兄弟连)

/** 类的学习**class 类名{    //用关键字&quot; var &quot;来声明变量,即创建了类的属性    var xxx = ;    //声明函数,即创建了类的方法。    f...
  • sun_96216
  • sun_96216
  • 2018-02-14 11:33:12
  • 12

php笔记 面向对象

  • 2012年12月29日 11:01
  • 27KB
  • 下载

php单例模式和工厂模式

  • 2009年05月22日 22:38
  • 54KB
  • 下载
收藏助手
不良信息举报
您举报文章:PHP面向对象笔记 —— 125 单例模式
举报原因:
原因补充:

(最多只允许输入30个字)