- 论坛徽章:
- 0
|
本帖最后由 bs 于 2011-03-06 23:42 编辑
以往在php环境下谈到的设计模式往往都是理论一大堆,加之php较少在实现大型应用方面,所以很多时候设计模式成了一种摆设,本文从较简单的设计模型中的单件模式说起,谈谈应用,阐述设计模型对于复杂环境中的大内涵.
从一个简单的例子着手,在一些应用中,我们希望有些对象是全局作用的,如下:
- include('example.class.php');
- $obj = new example();
- class a1
- {
- function ex()
- {
- global $obj;
- $obj->v = 1; //注意这里,需要调用外部对象
- }
- }
- class a2
- {
- function ex()
- {
- global $obj;
- $obj->v ++; //注意这里,再次调用外部对象
- }
- }
- $a1 = new a1;
- $a1->ex();
- $a2 = new a2;
- $a2->ex();
复制代码 从上面简单的例子看到,$obj对象被其它多个对象所使用,这时通常需要的几个步骤:
1. include类文件
2. 实例化
3. 在使用时global声明全局性
倘若有种情况需要在不同的对象中调用多个外部对象,那么情况有可能就是如下:
- include('example.class.php');
- $obj = new example();
- include('example2.class.php');
- $obj2 = new example2();
- ...
- $obj3
- $obj4
- $obj_n
- ...
- class a1
- {
- function ex()
- {
- global $obj;
- $obj->v = 1;
- global $obj2;
- $obj2->v = 1;
- ...
- global $obj_n;
- $obj_n->v = 1;
- }
- }
- class a2
- {
- ...
复制代码 局面开始不好收拾了,于是我们使用一种方法封装这个过程,首先定义一个类,这个类专门负责将另一个指定的类自动实例化成对象:
- class Singleton
- {
- private $objs;
- public function instance($obj)
- {
- if($this->objs[$obj] == null) //判断是否已经实例化
- {
- include($obj.'.class.php');
- $this->objs[$obj] = new $obj;
- }
- return $this->objs[$obj];
- }
- }
- $Singleton = new Singleton();
复制代码 那么之前的局面就演变成如下:
- ...
- class a1
- {
- function ex()
- {
- global $Singleton; //只需一次global声明
- $Singleton->reg('example')->v = 1;
- $Singleton->reg('example2')->v = 1;
- ...
- $Singleton->reg('example_n')->v = 1;
- ...
- }
- }
- class a2
- {
- ...
复制代码 那么其中通过$Singleton对象访问类就是经典的单件模式了,这边仅仅是说明了单件模式概念,以下说明使用单件模式的好处.
一.文件包含与对象实例化的透明化
我们发现上边在使用$Singleton仍然需要global声明,这时可以使用函数来"包装"
- function instance($class_name)
- {
- static $instance;
- if($instance == false)
- $instance = new Singleton();
- return $instance->reg($class_name); //调用Singleton对象,实例化类并返回对象
- }
复制代码 那么最终的调用就是这样的
- ...
- class a1
- {
- function ex()
- {
- //这里我们无需使用global,直接使用example类生成的对象
- instance('example')->v = 1;
- instance('example2')->v = 1;
- ...
- }
- }
- class a2
- {
- ...
复制代码 这时我们看到使用一个外部对象就变得简单而清晰了,我们无需关注example类所在文件的包含和实例化就能直接使用,
这就是使用单件模式对对象透明化的作用.
二.全局(作用域)应用
通过之前的代码得知,我们可以在任何时候使用Singleton得到我们希望使用的对象:
- class a1
- {
- function ex()
- {
- instance('example')->v = 1; //使用单件模式针对example类生成对象并进行操作
- ...
- }
- }
- ...
- class a2
- {
- function ex()
- {
- instance('example')->v ++; //在不同作用域对同一个对象进行操作
- ...
- }
- }
复制代码 在a1和a2的类中调用example实现的对象时,无需考虑作用域及global声明,实现跨全局对象的应用.
三.事务性/一致性的应用
在一些多线程的语言中,有时希望在同一时间只能有一个线程对对象进行操作,这是线程安全问题,而在php中,类似的情况是资源竞争的解决,如对共享数据的读写,而使用单件模式则很容易做到,在原有单件模式的基础上,增加了事务性
- class Singleton_safe
- {
- private $objs;
- private $mutex;
- public function reg($obj)
- {
- if($objs[$obj] == null) //判断是否已经实例化
- {
- include($obj.'.class.php');
- $this->mutex[$obj] = sem_get(fileinode($obj.'.class.php'),1,0666,true);
- sem_acquire($this->mutex[$obj]); //这边使用信号量做同步
- $this->objs[$obj] = new $obj;
- }
- return $this->objs[$obj];
- }
- function __destruct()
- {
- foreach($this->mutex as $sem_id)
- {
- sem_release($sem_id); //单件模式下析构时删除所有对象的信号量锁
- //sem_remove($sem_id);
- }
- }
- }
复制代码 当然,和其它语言不一样,这个简单的例子实现的事务周期是对象在整个php进程的运行期间,这样保证了在调用Singleton_safe实现单例模式下,派生对象的所有操作是系统唯一的.
*四.其它扩展
有时在使用或调试对象时,需要记录对象的调用次数,可增加一些记数功能,
- class Singleton
- {
- private $objs;
- private $record = 0;
- public function reg($obj)
- {
- if($this->objs[$obj] == null) //判断是否已经实例化
- {
- include($obj.'.class.php');
- $this->objs[$obj] = new $obj;
- }
- $this->record[$obj]++; //累计对象的使用次数
- return $this->objs[$obj];
- }
- public get_record($obj_name)
- {
- return $this->record[$obj_name]; //获取对象的使用次数
- }
- }
- ....
- function instance($class_name == null)
- {
- static $instance;
- if($instance == false)
- $instance = new Singleton();
- if($class_name == null) return $instance;
- return $instance->reg($class_name);
- }
复制代码 使用时
- instance('example')->v = 1;
- instance('example')->v++;
- echo 'example被使用次数为:',instance()->get_record('example');//2
复制代码 此外在一些其它语言上,如Cpp上也可结合对象的创建与销毁等内存管理工作.
单件模式是设计模式中较简单同时也是使用最为频繁的模式之一,仅仅这样一个简单的实现便可以帮我们做很多事,也让我们更多更有必要地去了解设计模式的价值所在.
另外在代码中存在Multiton模式的争议
更纯粹的Singleton如下
- //同上
- function instance($class_name)
- {
- static $instance;
- if($instance[$class_name] == false)
- $instance[$class_name] = new Singleton($class_name);
- return $instance[$class_name]
- }
- ...
- class Singleton
- {
- function __construct($class_name)
- {
- include($class_name.'.class.php');
- return new $class_name;
- }
- ...
- }
复制代码 调用上完全相同,算是重新做了Singleton和Multiton区别 |
|