PHP模式设计之单例模式、工厂模式、注册树模式、适配器模式、观察者模式
php模式设计之单例模式
什么是单例模式?
单例模式是指在整个应用中只有一个实例对象的设计模式
为什么要用单例模式?
php经常要链接数据库,如果在一个项目中频繁建立连接数据库,会造成服务器资源的很大浪费,在团队合作项目中,也能够避免不同的程序员实例自己的对象,造成人为的系统消耗。
单例模式的三大原则
1.构造函数需要标记为非public(防止外部使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化
2.拥有一个保存类的实例的静态成员变量$_instance
3.拥有一个可以访问这个实例的公共静态方法
示例代码
<?php /** * php设计模式之单例模式 */ class Db { static private $_instance; final protected function __construct() { # code... } public static function getInstance() { if (!self::$_instance instanceof self) { self::$_instance=new Db(); } return self::$_instance; } public function connect() { //链接数据库 } } ?>
php模式设计之工厂模式
什么是工厂模式?
工厂模式是指根据不同的参数生成不同的类实例。
为什么要用工厂模式?
减少代码进行复制粘帖,耦合关系重,牵一发动其他部分代码,比如在项目中很多地方实例化某个类,现在突然发现类名不合适或者类中需要添加构造函数参数,难不成需要一个个改?典型的例子就是连接数据库,php中连接数据库有好几种方法,mysql扩展,mysqli扩展等,这个时候就可以用到工厂模式。
示例代码
<?php /** * php设计模式之工厂模式 */ class Db { public static function factory($param){ switch ($param) { case 'mysql': return new Class1(); break; case 'mysqli': return new Class2(); break; case 'mssql': return new Class3(); break; } } } interface Connect { public function fun1($param); } class Class1 implements Connect { public function fun1($param){ //具体实现 } } class Class2 implements Connect { public function fun1($param){ //具体实现 } } class Class3 implements Connect { public function fun1($param){ //具体实现 } } ?>
php模式设计之注册树模式
什么是注册树模式?
注册树模式通过将对象实例注册到全局对象树上,需要的时候将对象从全局对象树上取下来
为什么要用工厂模式?
前面讲到的单例模式解决了在整个项目中创建唯一对象的问题,工厂模式解决了不通过new解决实例对象的问题,考虑的是项目扩展与维护。总得来说单例模式和工厂模式可以产生更加合理的对象,那么怎么方便统筹调用这些对象呢,这时候就用到了注册树模式,不管你是单例模式,工厂模式还是二者结合生成的对象,都统统给我注册到树上,用某个对象的时候,直接从树上取下来就好。
示例代码
<?php /** * 单例模式 */ class Signal { static private $_instance; final protected function __construct() { # code... } public static function getInstance() { if (!self::$_instance instanceof self) { self::$_instance=new Signal(); } return self::$_instance; } public function connect() { //链接数据库 } } /** * 工厂模式 */ class Db { public static function factory($param='') { switch ($param) { case 'mysql': return new Class1(); break; case 'mysqli': return new Class2(); break; case 'mssql': return new Class3(); break; default: return Signal::getInstance(); } } } interface Connect { public function fun1($param); } class Class1 implements Connect { public function fun1($param) { //具体实现 } } class Class2 implements Connect { public function fun1($param) { //具体实现 } } class Class3 implements Connect { public function fun1($param) { //具体实现 } } /** *注册树模式 */ class Register { static protected $objects; /** * 插入对象实例 * @param string $alias * @param object $object 对象实例 */ public static function set($alias,$object) { self::$objects[$alias]=$object; } /** * 撤销对象实例 * @param string $alias */ public static function _unset($alias) { unset(self::$objects[$alias]); } /** * 获取对象实例 * @param string $alias * return object */ public static function get($alias) { return self::$objects[$alias]; } } Register::set('signal',Db::factory()); $signal=Register::get('signal'); $signal->connect(); ?>
php模式设计之适配器模式
什么是适配器模式?
把对某些相似的类的操作转化为一个统一的"接口"--适配器,或者比喻为某个"界面",统一或者屏幕那些类的细节.适配器模式还构造了一种"机制",使"适配"的类很容易增减,而不用修改与之交互的代码,符合减少代码间的耦合。
为什么要用适配器模式?
主要应用于"希望复用一些现成的类,但是接口又与复用环境不一致"的情况
示例代码
1.源(Adaptee)角色:Toy系列类保持不变
<?php abstract class Toy { public abstract function openMouth(); public abstract function closeMouth(); } class Dog extends Toy { public function openMouth() { echo "Dog open Mouth\n"; } public function closeMouth() { echo "Dog close Mouth\n"; } } class Cat extends Toy { public function openMouth() { echo "Cat open Mouth\n"; } public function closeMouth() { echo "Cat close Mouth\n"; } } ?>
2.目标(Target)角色接口
<?php //目标角色:红枣遥控公司 interface RedTarget { public function doMouthOpen(); public function doMouthClose(); } //目标角色:绿枣遥控公司及 interface GreenTarget { public function operateMouth($type = 0); } ?>
3.适配器角色代码实现
//类适配器角色:红枣遥控公司 class RedAdapter implements RedTarget { private $adaptee; function __construct(Toy $adaptee) { $this->adaptee = $adaptee; } //委派调用Adaptee的sampleMethod1方法 public function doMouthOpen() { $this->adaptee->openMouth(); } public function doMouthClose() { $this->adaptee->closeMouth(); } } //类适配器角色:绿枣遥控公司 class GreenAdapter implements GreenTarget { private $adaptee; function __construct(Toy $adaptee) { $this->adaptee = $adaptee; } //委派调用Adaptee:GreenTarget的operateMouth方法 public function operateMouth($type = 0) { if ($type) { $this->adaptee->openMouth(); } else { $this->adaptee->closeMouth(); } } }
4.测试用例
<?php class testDriver { public function run() { //实例化一只狗玩具 $adaptee_dog = new Dog(); echo "给狗套上红枣适配器\n"; $adapter_red = new RedAdapter($adaptee_dog); //张嘴 $adapter_red->doMouthOpen(); //闭嘴 $adapter_red->doMouthClose(); echo "给狗套上绿枣适配器\n"; $adapter_green = new GreenAdapter($adaptee_dog); //张嘴 $adapter_green->operateMouth(1); //闭嘴 $adapter_green->operateMouth(0); } } $test = new testDriver(); $test->run(); ?>
php模式设计之观察者模式
什么是观察者模式?
从面向过程的角度来看,首先是观察者向主题注册,注册完之后,主题再通知观察者做出相应的操作,整个事情就完了
从面向对象的角度来看,主题提供注册和通知的接口,观察者提供自身操作的接口。(这些观察者拥有一个同一个接口。)观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。耦合度相当之低
为什么要用观察者模式?
观察者模式更多体现了两个独立的类利用接口完成一件本应该很复杂的事情。不利用主题类的话,我们还需要不断循环创建实例,执行操作。而现在只需要创建实例就好,执行操作的事儿只需要调用一次通知的方法就好啦
示例代码
<?php // 主题接口 interface Subject{ public function register(Observer $observer); public function notify(); } // 观察者接口 interface Observer{ public function watch(); } // 主题 class Action implements Subject{ public $_observers=array(); public function register(Observer $observer){ $this->_observers[]=$observer; } public function notify(){ foreach ($this->_observers as $observer) { $observer->watch(); } } } // 观察者 class Cat implements Observer{ public function watch(){ echo "Cat watches TV<hr/>"; } } class Dog implements Observer{ public function watch(){ echo "Dog watches TV<hr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TV<hr/>"; } } // 应用实例 $action=new Action(); $action->register(new Cat()); $action->register(new People()); $action->register(new Dog()); $action->notify(); ?>