面向对象:单例模式

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
这一题很典型的体现
static 静态方法的特点: 不绑定$this

***/


class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}

class B
{
function bar()
{
A::foo();
}
}

$a = new A();
$a->foo(); // foo是普通方法,$a绑定到$this,因此,$this is defined(A);
A::foo(); // 这样调用,是不规范的.$this is not defined

$b = new B();
$b->bar(); // bar是普通方法,$b绑定到$this,bar(){A::foo-这里是静态调用,不操作$this}
// $this is defined (B);
B::bar(); // this is not defined
?>

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
总结self, parent的用法

self: 本类(不要理解成本对象)
parent: 父类

在引入自身的静态属性/静态方法
以及父类的方法时,可以用到.

用法:
self::$staticProperty
self::staticMothed;
parent::$staticProperty
parent::Mothed;
***/
/*
class Human {
static public $head = 1;

public function say() {
echo Human::$head,'<br />';
}
}


echo Human::$head,'<br />'; // 1

$lisi = new Human();
$lisi->say(); //
*/
// 某一天,类名要统一,规范化. Human不叫Human了,叫cHuman
// 导致类内部,凡引用到自身类名的也要改


class cHuman {
static public $head = 1;

public function say() {
echo self::$head,'<br />';
}


}

echo cHuman::$head,'<br />'; // 1

$lisi = new cHuman();
$lisi->say(); //

 

class Stu extends cHuman {
static public $head = 2;

public function say() {
echo self::$head,'<br />';
echo '父类只有',parent::$head,'<br />';
}

}

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


// ========一位同学的疑问,$this,还用parent====//
class a{
public function a1(){
echo 'this is class function a1()';
}

}
class b extends a{
public function b1(){
$this->a1();
}

public function b2(){
parent::a1();
}
}

$b = new b();
$b->b1();
$b->b2();

/*
上面2个调用,显示效果一样的,
如果从速度角度看,理论上parent::稍快一点点.
因为在子类寻找a1方法,寻找不到,再去其父类寻找.

但是从面向角度看,继承过来的,就是自己的.
$this 更符合面向的思想.

举一个反例
class a {
}

class b extends a {
}

class c extends b {
}
...
...

class f extends e {
parent::parent::parent::
总不能这么写吧?
}

*/

 

<?php


class Human {

protected $age = 23;
public function say() {
echo $this->age,'<br />';
}
}


class Stu extends Human{
protected $age = 15;

public function say1() {
$this->say();
}

public function say2() {
parent::say();
}

public function say3() {
echo $this->age;
}
}

$ming = new Stu();

print_r($ming);

$ming->say1();
$ming->say2();
$ming->say3();


?>

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
单例模式

先看场景:
多人协同开发, 都要调用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()行为.
我们可以从技术上,用单例模式来解决


注:单例常用也常考,请认真练习
***/

echo '<pre>';

/*
第一步:一个普通的类
这个普通类,可以new 来实例化
这显然不是单例

class single {

}

$s1 = new single();
$s2 = new single();
$s3 = new single();
*/


/*
第二步:看来new是罪恶之源,干脆不让new了
我们把构造方法 保护/私有
外部不能new了
--但引出一个问题,不能new,那得不到对象,这不是单例,这是0例模式


class single {
protected function __construct() {

}
}

$s1 = new single();

*/


/*
第三部,通过内部的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);

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 最终的 详见05.php

 

 

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....
// 请同学们自行预习

 

<?php
/****
燕十八 公益PHP讲堂

论 坛: http://www.zixue.it
微 博: http://weibo.com/Yshiba
YY频道: 88354001
****/


/***
====笔记部分====
final 最终的
这个关键词 在PHP中,可以修饰类,方法名,但不能修饰属性

final 修饰类,则此类 不能够被继承

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


在java中,final也可以修改属性,此时属性值,就是一个常量,不可修改.
问:PHP的类中,可不可以有常量.
答:有
***/

/*
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()
*/

 

 

 

 

posted on 2012-11-19 14:59  besile  阅读(221)  评论(0)    收藏  举报