切换风格

Wizard Sky California Sunset glow Black Cloud Beige Dragon Lavender NewYear City Snow Flowers London
收藏本站XSS平台字符串转换jsfuck
about PHP的单例模式[复制链接]
发表于 2014-3-25 15:22:02 | 显示全部楼层 |!read_mode!
很久之前写的文章        
<?php
//今晚的一份笔记  
//Author :        越王  
//Date   :        2013/9/25 凌晨1点25 

/*
        什么叫单例模式呢   顾名思义  是类的单例模式   单例中的 "例"也就是类的实例了 而类的实例 也就是对象了   嘿嘿 
        
        那么单例模式有毛作用呢   举个例子来说  假如我们有一个数据库操作类  
       
        代码如下:

*/


class db {
        private $host=null;
        private $username=null;
        private $password=null;
        
        public function __construct($host,$username,$password){
                $this->host = $host;
                $this->username = $username;
                $this->password = $password;
        }
        public function connection(){
                $mysql = mysql_connect($this->host,$this->username,$this->password);
                if(mysql_errno()){
                        echo "connect error ".mysql_error();
                        exit();
                }
                return $mysql;        
        }

}

$db = new db("localhost","root","xxx");   // A程序员 对象引用名称为$db

$mysql = new db("localhost","root","xxx");   // B程序员 对象引用名称为 $mysql




/*
        不同的页面中调用这个类 实例化成对象的时候  不同的程序员 所定义的对象的引用名称是不同的   他们都占用内存空间  这样以来就造成了  资源的浪费  

        如上所示  A 程序员 和  B 程序员 所定义的对象的引用是不同的  他们都占有内存空间    那么有没有一种方法能解决 无论哪种对象的引用所指向的内存
        
        空间都是同一块内存空间  也就是你定义怎样的对象引用名称  他们指向的都是同一个对象呢 ????    答案就是单例模式 


        在此之前 我们先了解一点前置知识 就是 static关键字 和final关键字    我们知道static关键字所修饰的属性和方法是 属于类的 而非对象   他不依赖于对象存在还是不存在 

        一旦一个属性或者是方法被static关键字修饰 那么即使我们不创建对象 我们也能访问类中的属性和方法  并且一旦类被实例化成不同的对象  被static关键字 修饰的属性和方法

        是各个对象之间所共用的  

        还是举例子说明吧  示例代码如下 :

*/



class Add {
        static public $sum=1;
        
        public function __construct(){
                self::$sum++;
        }

        public function add(){
                return self::$sum;
        }
}

echo Add::$sum;  //输出结果为1   看 我们并没有实例化对象 也能访问$sum
print "\n";

//我们连续实例化三个对象  再看看sum的值是 多少 

$obj_1 = new Add;
$obj_2 = new Add;
$obj_3 = new Add;

echo Add::$sum; //4
print "\n";

echo $obj_1->add(); //4
print "\n";

echo $obj_2->add(); //4
print "\n";

echo $obj_3->add(); //4 
print "\n";




//结果都为4  我们可以看到通过static修饰的属性sum是各个对象之间共用的 

// 那么 final关键字 是干毛用的呢   final关键字 如果修饰的是类 那么这个类 是不可以被继承的     如果类中的方法使用final关键字来修饰 那么在子类中
// 这个方法是不能被重写的  
// 好了  关于基础知识的介绍 就到这里了  下面进入我们的正题吧  :单例模式  



//我们要的是 通过不用的对象引用都能达到指向同一对象内存空间的目的  首先我们要保证类不能随便的被new 因为每new一次就会产生不同的实例  我们可以把__construct()方法用protected修饰

//这样一来  就不能随便的new了   那么我们怎么样来获得实例呢  我们可以通过在内部静态方法中new 自身  外部通过  类名::静态方法名  这种方式 来获得 实例   但是这样一来不同的程序员

//所获得实例还是不同的  所以得在静态方法中加判断  我们首先在类中 定义一静态属性  第一次调用静态方法的时候 就将类自身的实例赋值给这个静态属性  以后每次调用这个静态方法的时候就

//判断一下 静态属性所代表的类的实例是不是这个类本身的实例   如果是直接返回静态属性所代表的实例 就ok了   

//示例代码如下:


class single {
        public $hash = 0; //随机测试码
        static protected $ins=NULL; //代表类实例的静态属性

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

        static public function getInstance(){
                if(self::$ins instanceof self){ //instanceof 关键字是用来判断某个对象是不是某个类的实例用的  
                        return self::$ins;
                }
                self::$ins = new self; //将自身的实例赋值给 $ins
                return self::$ins;
        }


}


$obj_1 = single::getInstance();
$obj_2 = single::getInstance();

if($obj_1 === $obj_2){
        echo "It's the same object\n";
        print_r($obj_1); // [hash] => 67055
        print "\n";
        print_r($obj_2); // [hash] => 67055
        print "\n";
}else {
        echo "It isn't the same object\n";
}



//通过上面的代码 我们看到两个实例中的 随机码都是相同的  说明 我们的目的达到了  这就是单例模式  貌似是问题圆满了  其实不然   如果我们通过一个子类继承他

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

//然后我们再实例化两个对象看看 

$obj_1 = new test();

$obj_2 = new test();

print_r($obj_1); //[hash] => 95220

print_r($obj_2); //[hash] => 19176



//我们发现 通过重写类中的方法  两个对象又不是 不同的对象了 那么该怎么办呢  办法就是final  因为前边我们说过通过final关键字修饰的方法子类中是不能重写的

//加上final关键字 



class single {
        public $hash = 0; //随机测试码
        static protected $ins=NULL; //代表类实例的静态属性

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

        static public function getInstance(){
                if(self::$ins instanceof self){ //instanceof 关键字是用来判断某个对象是不是某个类的实例用的  
                        return self::$ins;
                }
                self::$ins = new self; //将自身的实例赋值给 $ins
                return self::$ins;
        }


}


class test_1 extends single {
                
}


$obj_3 = test_1::getInstance();

$obj_4 = test_1::getInstance();


print_r($obj_3); //[hash] => 6430

print_r($obj_4); //[hash] => 6430


//ok 问题圆满解决了  

发表于 2014-3-25 20:41:37 | 显示全部楼层
不错 简明扼要 突出重点 生动形象 引人入胜 ,期待多发一些楼主对php编程思想的经验和见解
发表于 2014-3-31 18:30:12 | 显示全部楼层
店小二01 发表于 2014-3-25 20:41
不错 简明扼要 突出重点 生动形象 引人入胜 ,期待多发一些楼主对php编程思想的经验和见解

好滴
发表于 2014-7-27 00:03:12 | 显示全部楼层
很不错,现在越来越屌了。但是为什么是酱油党了呢
发表于 2015-5-11 20:08:53 | 显示全部楼层
这个要是看书或是看视频别人讲出来的理论,真的要让人跪了
发表于 2015-5-12 10:41:54 | 显示全部楼层
学习了;。。。

代码区

GMT+8, 2019-9-23 22:06

Powered by Discuz! X2

© 2001-2018 Comsenz Inc.

回顶部