单例模式完成开发过程
先看场景:
多人协同开发, 都要调用mysql类的实例
如果用svn知道,好多人一起开发,再提交各自的文件.
A:
$mysql = new mysql();
$mysql->query....
测试通过
B:
$db = new mysql();
测试通过
…
…
两人的代码要合到一块,如下
$mysql = new mysql();
$mysql->query....
$db = new mysql();
两个mysql类的实例,而且,每new一下,还要连接一次数据库.
显然,一个页面呢,有一个mysql类的实例就够了.如果限制,让多人开发,无论你怎么操作,只能得到一个对象呢?
1:开会时,经理说:有一个$db变量,是系统自动初始化的,就是mysql类的实例.
大家都用他.谁敢new mysql(),开除.
2:这是行政手段,不能阻止技术上的new mysql()行为.
我们可以从技术上,用单例模式来解决
第一步
一个普通的类
这个普通类,可以new 来实例化
这显然不是单例
class single {
}
$s1 = new single();
$s2 = new single();
$s3 = new single();
第二步
看来new是罪恶之源,干脆不让new了
我们把构造方法 保护/私有
外部不能new了
class single {
protected function __construct() {
}
}
$s1 = new single(); //报错
–但引出一个问题,不能new,那得不到对象,这不是单例,这是0例模式
第三步
通过内部的static方法,来调用
class single{
public $hash; //随机码,在这里用来判断类是否相同
protected function __construct(){
$this->hash=mt_rand(1,99999);
}
static public function getInstance(){
return new self();
}
}
$s1 = single::getInstance();
$s2 = single::getInstance();
// 两个对象什么时间相等?
// 答:只有指向一个对象地址的时候,才相等.
print_r($s1);
print_r($s2); //两者的$hash值不相同
if($s1 === $s2) {
echo '是一个对象';
} else {
echo '不是一个对象'; //结果不是一个对象
}
第四步,通过内部的static方法实例化,
并且,把实例保存在类内部的静态属性上
class single {
public $hash; //随机码
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 = single::getInstance();
$s2 = single::getInstance();
print_r($s1);
print_r($s2);
if($s1 === $s2) {
echo '是一个对象'; //此处正确
} else {
echo '不是一个对象';
}
上面已经完成了一个单例模式类,但是一继承就出现了问题:
class test extends single {
public function __construct() {
parent::__construct();
}
}
$t1 = new test();
$t2 = new test();
print_r($t1);
print_r($t2);
// 问题1:我们辛苦写的单例,继承一下就不灵了.
// 解决 final 最终的
介绍final
这个关键词 在PHP中,可以修饰类,方法名,但不能修饰属性
final 修饰类,则此类 不能够被继承
final 修饰方法,此方法不影响继承,但是此方法 不允许重写
在java中,final也可以修改属性,此时属性值,就是一个常量,不可修改.
问:PHP的类中,可不可以有常量.
答:有,const与define
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(); // final 方法可以继承
class FreshMan extends Stu{
public function say() {
echo '我要出国,做美利坚人';
}
}
/*
Fatal error: Cannot override final method Human::say()
*/
继续完成单例模式继承一下出现的问题
class s {
public $hash; //随机码
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 t extends s {
}
$t1 = t::getInstance();
$t2 = t::getInstance();
$t3 = clone $t2;
if($t1 === $t2) {
echo '是一个对象<br />'; //此处对
} else {
echo '不是一个对象<br />';
}
if($t3 === $t2) {
echo '是一个对象<br />';
} else {
echo '不是一个对象<br />'; //此处对
}
clone又多出一个对象, 试问,如何解决?
提示: 请看魔术方法 clone!
魔术方法很多, __construct, __destruct, __clone,__callstatic….