Chinaunix首页 | 论坛 | 博客
  • 博客访问: 480376
  • 博文数量: 95
  • 博客积分: 2117
  • 博客等级: 大尉
  • 技术积分: 2301
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-16 21:10
个人简介

辽宁铁岭人,现居大连。1970年生。 先后供职于 中国国际海运网、大连学堂科技、大连华仁视线网络科技有限公司、大连中科海云科技有限公司,任职技术总监。 精通PHP、JAVA、Javascript、HTML、CSS等网络编程技术及Linux操作系统。 精通面向对象编程、设计模式、重构及互联网产品设计。

文章分类

全部博文(95)

文章存档

2013年(31)

2012年(2)

2011年(34)

2010年(25)

2008年(3)

分类: Python/Ruby

2011-06-26 12:43:31

基于PHP语言自身的一些特性,在实现设计模式时,有着不同于JAVA等语言的特点,这里说一说实现单例模式时需要注意的问题。

先看看《PHP高级程序设计——模式、框架与测试》(Pro PHP——Patters, Frameworks, Testing and More)中的例子(书中每18页):

  1. class Database {
  2.     private $_db;
  3.     static $_instance;

  4.     private function __construct() {
  5.         $this->_db = pg_connect('dbname=example_db');
  6.     }

  7.     private function __clone() {}; //此处中译本漏掉了function关键字

  8.     public static function getInstance() {
  9.         if ( ! (self::$_instance instanceof self) ) {
  10.             self::$_instance = new self();
  11.         }
  12.         return self::$_instance;
  13.     }

  14.     public function query($sql) {
  15.         return pg_query($this->_db, $sql);
  16.     }
  17. }

这里面有个问题,就是用继承的方式可以使用构造函数生成子类的对象,可能在不小心的情况下破坏了单件机制。代码如下:

  1. class subDatabase
  2. {
  3.     public function __construct()
  4.     {
  5.         $this->_db = pg_connect('dbname=example_db');
  6.     }
  7. }


在JAVA中,这种情况是不会出现的,这是因为JAVA的构造函数无论显式或隐式,都必须调用父类的构造函数,而父类的构造函数一旦被设置为private,就不能为子类访问。因此,拥有私有构造函数的类将不能被子类化(继承)。
而在PHP中,构造函数无须显式或隐式地调用父类的构造函数,就造成了上面的情况。

堵住这个漏洞的办法也很简单,只要将Database的构造函数设置为final,子类将无法对其进行重写,虽然仍然能够子类化该类,但却无法实例化。

代码如下:

  1. class Database {
  2.         private $_db;
  3.         static $_instance;
  4.         final private function __construct() {
  5.             $this->_db = pg_connect('dbname=example_db');
  6.         }
  7.         private function __clone() {}; //此处中译本漏掉了function关键字
  8.         public static function getInstance() {
  9.             if ( ! (self::$_instance instanceof self) ) {
  10.                 self::$_instance = new self();
  11.             }
  12.             return self::$_instance;
  13.         }
  14.         public function query($sql) {
  15.             return pg_query($this->_db, $sql);
  16.         }
  17.     }
至于类中私有化__clone函数的作用,请见《PHP高级程序设计——模式、框架与测试》第18页的讲解。

更简单的方式,给类添加final,使其无法被继承:

  1. final class Database {
  2.       private $_db;
  3.       static $_instance;
  4.       private function __construct() {
  5.            $this->_db = pg_connect('dbname=example_db');
  6.       }
  7.       private function __clone() {}; //此处中译本漏掉了function关键字
  8.       public static function getInstance() {
  9.           if ( ! (self::$_instance instanceof self) ) {
  10.                 self::$_instance = new self();
  11.           }
  12.           return self::$_instance;
  13.       }
  14.       public function query($sql) {
  15.             return pg_query($this->_db, $sql);
  16.       }
  17. }
再来说说JAVA中实现单例的“懒汉模式”和“饿汉模式”。其中饿汉模式是指在类创建时就创建了实例,具体代码类似于:

  1. public class Singleton{
  2.     private static Singleton singleton = new Singleton ();
  3.     private Singleton (){}
  4.     public Singleton getInstance(){
  5.            return singletion;
  6.     }
  7. }
此种方式,在PHP中无法实现,因为PHP中的类静态变量只能用常量赋值,不能用变量、表达式赋值。因此PHP中仅能实现“懒汉模式”。
阅读(2092) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~