<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[为什么要使用PHP单例模式及应用实例+PHP设计模式笔记：使用PHP实现单例模式]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Mon, 18 Mar 2013 10:03:59 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：在以前初始化一个数据库句柄：<br/><textarea name="code" class="php" rows="15" cols="100">
 $db = new DB(...);
 $db-&gt;getUserInfo();
 ......
</textarea><br/>为何都这样写单例模式？层层分析：<br/>http://www.cnblogs.com/hongfei/archive/2012/07/07/2580994.html<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
&nbsp;&nbsp;&nbsp;&nbsp;class SqlHelper&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private static $_instance;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public $_dbname;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function __construct()&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//getInstance()方法必须设置为公有的,必须调用此方法
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static function getInstance()&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//对象方法不能访问普通的对象属性，所以$_instance需要设为静态的
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (self::$_instance===null) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_instance=new SqlHelper();//在调用getInstance的时候还未实例化出对象，所以在getInstance函数中使用$this肯定也会报错（Fatal error: Using $this when not in object context）
那如何解决呢？ (也就是说写$this时这个对象都不在，立即会报错。getInstance（）方法设为静态的，根据静态的定义，她只能被类而不是对象调用，将$_instance也设为静态的即可。说白了就是用self这个类调，而不能用$this。)
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$_instance=new SqlHelper();//方式一&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$_instance=new self();//方式二&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self::$_instance;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public function getDbName()&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo $this-&gt;_dbname;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public function setDbName($dbname)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_dbname=$dbname;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
//&nbsp;&nbsp;&nbsp;&nbsp;$sqlHelper=new SqlHelper();//打印：Fatal error: Call to private SqlHelper::__construct() from invalid context 
&nbsp;&nbsp;&nbsp;&nbsp;$A=SqlHelper::getInstance();//打印：构造函数被调用。（这块有的认为构造函数不被调用，也是不对的）
&nbsp;&nbsp;&nbsp;&nbsp;$A-&gt;setDbName(&#039;数据库名&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;$A-&gt;getDbName();
//&nbsp;&nbsp;&nbsp;&nbsp;unset($A);//移除引用
&nbsp;&nbsp;&nbsp;&nbsp;$B=SqlHelper::getInstance();
&nbsp;&nbsp;&nbsp;&nbsp;$B-&gt;getDbName();
&nbsp;&nbsp;&nbsp;&nbsp;$C=SqlHelper::getInstance();
&nbsp;&nbsp;&nbsp;&nbsp;$C-&gt;getDbName();
&nbsp;&nbsp;&nbsp;&nbsp;
?&gt;
</textarea><br/><br/>——————————————————————————————————————<br/>上面Url里提到各种调用调不了，出问题的一个小小总结如下，也有总结不对的，说是静态函数被类调用不需要执行析构函数是不对的，执行了，但没有创建对象是真：<br/>在php中，访问类的方法/变量有两种方法： <br/>1. 创建对象$object = new Class()，然后使用”-&gt;”调用：$object-&gt;attribute/function，前提是该变量/方法可访问。 <br/>2. 直接调用类方法/变量：class::attribute/function，无论是静态/非静态都可以。但是有前提条件： <br/>A. 如果是变量，需要该变量可访问。 <br/>B. 如果是方法，除了该方法可访问外，还需要满足： <br/>b1) 如果是静态方法，没有特殊条件； <br/>b2) 如果是非静态方法，需要改方法中没有使用$this，即没有调用非静态的变量/方法，当然，调用静态的变量/方法没有问题。 <br/><br/>然后我们再看一下使用$object-&gt;… 和使用class::… 都有什么区别： <br/>1. 使用$object-&gt;… ，需要执行构造函数创建对象； <br/>2. 使用class::… 调用静态方法/变量，不需要执行构造函数创建对象； <br/>3. 使用class::… 调用非静态方法/变量，也不需要执行构造函数创建对象。 <br/><br/>然后奇怪的地方就出来了，既然2和3都一样，那静态方法/变量存在还有什么意义呢？ <br/>差异还是显然存在的，如下： <br/>1. 静态变量 <br/>静态成员只保留一个变量值，而这个变量值对所有的实例都是有效，也就是说，所有的实例共享这个成员。 <br/>2. 静态方法 <br/>静态方法可以直接使用class::… 来调用，而非静态方法需要满足一定限制条件才能使用class::.. 的方法调用，如之前所述<br/><br/>来自：http://www.jb51.net/article/29717.htm<br/><br/>这时我们不得不重新初始化一个数据库句柄,试想多个应用场景下，这样的代码是多么可怕啊？！<br/><br/>有些朋友或许会说，我也可以不这样做啊，我直接利用global关键字不就可以了吗？的确，global可以解决问题，也起到了单例模式的作用，但是 OOP中，我们拒绝这样来编写代码，因为global存在安全隐患，请参考相关书籍，同时单例模式恰恰是对全局变量的一种改进，避免了那些存储唯一实例的 全局变量污染命名空间<br/> global $db;&nbsp;&nbsp;//OOP中，我们不提倡这样编写代码<br/>使用单例模式编码<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
......
//所有的应用情景只有一个数据库句柄资源，嘿嘿，效率老高了，
//资源也大大的得到节省，代码简洁明了：）
DB::getInstance()-&gt;addUserInfo();
DB::getInstance()-&gt;getUserInfo();
......

</textarea><br/>如有的KO框架里写的读取配置文件：<br/><textarea name="code" class="php" rows="15" cols="100">
$language[$lang][$group] = Config::instance(&#039;lang&#039;)-&gt;attach(new Config_File(&#039;i18n&#039;))-&gt;load($lang . DIRECTORY_SEPARATOR . $group);
这个就是单例调用时，叫链式写法了吧。对象层层调用。
</textarea><br/><br/>单例方式：就是只需一个实例。作为对象的创建方式，单例方式确保某一个类只需一个实例，而且自行实例化并向整个零碎提供这个实例，这个类我们称之为单例类。<br/><br/>单例方式的要点有三个：<br/>一是某个类只能有一个实例；<br/>二是它必需自行创建这个实例；<br/>三是它必需自行向整个零碎提供这个实例。<br/>上面我们讨论下为什么要运用PHP单例方式？<br/>多数人都是从单例方式的字面上的意思来理解它的用处, 以为这是对零碎资源的节省, 可以避免反复实例化, 是一种&quot;方案生育&quot;.&nbsp;&nbsp; 而PHP每次执行完页面都是会从内存中清算掉一切的资源. 因而PHP中的单例理论每次运转都是需求重新实例化的, 这样就失掉了单例反复实例化的意义了. 单单从这个方面来说, PHP的单例的确有点让各位绝望. 但是单例仅仅只需这个功用和运用吗? 答案能否认的,我们一同来看看。<br/>1. php的运用次要在于数据库运用, 所以一个运用中会存在大批的数据库操作, 在运用面向对象的方式开发时(废话), 假定运用单例方式, 则可以避免大批的new 操作耗费的资源。<br/>2. 假定零碎中需求有一个类来全局控制某些配相信息, 那么运用单例方式可以很方便的完成. 这个可以参看zend Framework的FrontController部分。<br/>3. 在一次页面央求中, 便于中止调试, 由于一切的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志，从而避免四处var_dump, echo。<br/>运用实例：<br/><br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php

/*
 * 单例方式举例,其要点如下: 1. $_instance 必需声明为静态的公有变量 2. 构造函数和克隆函数必需声明为公有的,这是为了避免内部顺序 new 类从而失掉单例方式的意义 3. getInstance()办法必需声明为公有的,必需调用此办法以前往独一实例的一个引用 4. ::操作符只能拜访静态变量或静态函数 5. PHP的单例方式是绝对而言的,由于PHP的解释运转机制使得每个PHP页面被解释执行后，一切的相关资源都会被回收。 也就是说，PHP在言语级别上没有办法让某个对象常驻内存。在PHP中，一切的变量都是页面级的，无论是全局变量， 还是类的静态成员，都会在页面执行终了后被清空,后果会重新树立新的对象，这样也就完全失掉了Singleton的意义。 不过,在理论运用中同一个页面中可以会存在多个业务逻辑,这时单例方式就起到了很重要的作用,无效的避免了反复 new 对象(注: new 对象会耗费内存资源)这么一个行为,所以我们说PHP的单例方式是绝对而言的
 */
class People &#123;
&nbsp;&nbsp;&nbsp;&nbsp;private static $_instance = NULL;
&nbsp;&nbsp;&nbsp;&nbsp;public $height = &#039;&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;public $age = &#039;&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;private function __construct() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;height = &#039;185&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;age = 25;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;private function __clone() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// do something
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;static public function getInstance() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (! self::$_instance instanceof self) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// echo &#039;lgh-big&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$_instance = new self ();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// for testing only
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// echo &#039;gdc-xiaoairener&#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self::$_instance;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;public function getHeight() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo $this-&gt;height;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;public function getAge() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo $this-&gt;age;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&#125;
function testInstance() &#123;
&nbsp;&nbsp;&nbsp;&nbsp;People::getInstance ()-&gt;getAge ();
&#125;

// begin to use the class

$lgh = People::getInstance ();
$lgh-&gt;getHeight ();

echo &#039;&lt;br /&gt;&#039;;
testInstance ();

?&gt;
</textarea><br/><br/><br/><br/><br/>更多参考：彻底认清PHP单例模式的本质<br/>http://blog.zol.com.cn/6211/article_6210156.html<br/>更多模式：http://coolshell.cn/articles/8961.html<br/>[PHP]单例模式遇上继承与重写：<br/>http://hi.baidu.com/kenking2008/item/75c34af3e36b4aea1a111f70<br/>php-可继承的单例模式例子-singleton：<br/>http://www.xinze.me/php-%E5%8F%AF%E7%BB%A7%E6%89%BF%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E4%BE%8B%E5%AD%90-singleton/
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 为什么要使用PHP单例模式及应用实例+PHP设计模式笔记：使用PHP实现单例模式]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>