设计模式笔记
个人理解:特定场景下,前辈对该问题合理处理方式的总结。设计模式不是为了设计模式而模式,是为了更好的处理问题,更好的提高程序的扩展性,健壮性,可读性,降低程序的复 杂性。在自己的程序中如遇相似的场景,借鉴使用,会起到指导性的作用,会达到事半功倍的效果。
开放封闭原则:软件实体(类、模块、函数等)应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。这样可以避免以后需要做修改的时候误删了原来其他部分的代码或出现其他的情况。我觉得也更好的提高了代码的可读性。
多态:面向对象的三大特性为封装、继承、多态。其中多态的理解就是多种状态。比如快捷键f1,在打开word的情况下出现word的帮助,在wps打开状态下就到了wps指南网址,picpick就到了他的帮助网址,其他软件可能同理调用自己的帮助吧。再比如写了一个people类,实例化时张三和李四都有各自的属性,这就是多个状态吧。
面向接口开发:现实中的例子,插头和插座生产厂家没有相互协商但是产品能用,因为他们遵循了行业的规范。
一、单例模式
特点:三私一公
单例模式是一种常见的设计模式,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、数据库操作、显卡的驱动程序常被设计成单例。
单例模式分3种:懒汉式单例、饿汉式单例、登记式单例。
$_instance必须声明为静态的私有变量,保存类的实例
之所以属性和getinstance方法声明为静态,因为为了防止外界实例化类,构造函数已经声明为私有了,就不能够创建对象,不能通过对象调用方法。单例是自己创建对象,将方法声明为static类自己就可以自己调用了,属性同理。
可以参考博文http://www.cnblogs.com/hongfei/archive/2012/07/07/2580994.html
<?php class Person{ private static $_instance;//属性为静态 private function __construct(){//私有化为了防止类外调用 } private function __clone(){//私有化为了防止类外调用 } public static function getInstance(){//因为没有创建类的对象就不能用对象调用方法,所以声明为静态 if(self::$_instance===null){ self::$_instance=new self(); } return self::$_instance; } } $s1=Person::getInstance(); $s2=Person::getInstance(); if($s1==$s2){ echo "同一实例"; }else{ echo "不同实例"; }
二、工厂模式
根据抽象程度不同,PHP工厂模式分为:简单工厂模式、工厂方法模式和抽象工厂模式
综合介绍工厂模式的三种博文http://www.phpddt.com/php/php-factory.html
①简单工厂模式
简单工厂模式又叫静态工厂方法模式,因为简单工厂模式是通过一个静态方法创建对象的
这里有个博客介绍简单工厂模式很清楚http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html
但是简单工厂模式修改时候,没遵循开放封闭原则。
<?php //抽象基类,或者用借口定义也行 abstract class Cal{ abstract public function deal($one,$two); } class Add extends Cal{ public function deal($one,$two){ return $one+$two; } } class Sub extends Cal{ public function deal($one,$two){ return $one-$two; } } //主要用来创建对象 class Factory{ // 简单工厂里的静态方法 public static function create($type){ if($type=="Add"){ return new Add(); }elseif($type=="Sub"){ return new Sub(); }else{ throw new Exception("error type",1); } } } /* //或每个类定义一个静态方法 class Factory{ // 简单工厂里的静态方法 static function createAdd() { return new Add(); } static function createSub() { return new Sub(); } } */ $add=Factory::create("Add"); echo $add->deal(2,3); $sub=Factory::create("Sub"); echo $sub->deal(6,3);
②工厂方法模式
给创建对象的类定义一个基类或者接口
<?php //抽象基类,或者用借口定义也行 abstract class Cal{ abstract public function deal($one,$two); } class Add extends Cal{ public function deal($one,$two){ return $one+$two; } } class Sub extends Cal{ public function deal($one,$two){ return $one-$two; } } //主要用来创建对象 Interface Factory{ public function create(); } class FactoryAdd implements Factory{ public function create(){ return new Add(); } } class FactorySub implements Factory{ public function create(){ return new Sub(); } } $add=new FactoryAdd(); $objadd=$add->create(); echo $objadd->deal(2,3); $sub=new FactorySub; $objsub=$sub->create(); echo $objsub->deal(6,3);
③抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口
<?php //抽象基类,或者用借口定义也行 abstract class Cal{ abstract public function deal($one,$two); } class Add extends Cal{ public function deal($one,$two){ return $one+$two; } } class Sub extends Cal{ public function deal($one,$two){ return $one-$two; } } //主要用来创建对象 Interface Factory{ public function createA(); public function createB(); } class FactoryAdd implements Factory{ public function createA(){ return new Add(); } public function createB(){ return new Sub(); } } $factory=new FactoryAdd(); $objadd=$factory->createA(); echo $objadd->deal(2,3); $objsub=$factory->createB(); echo $objsub->deal(6,3);
三、观察者模式
理解:就是在被观察者发生变化是通知所有观察他的人。比如我的的手机通讯录,我是被观察者,需要因为我的变化接到通知的人,首先得通过我的注册方法,register来将你的信息记录到我的通讯录中,这个用一个数组实现即可。然后我还有一个方法donotify()就是在我状态变化后,通知你们没一个人.因为你们每一个人都在我的通讯录中,我就遍历他让她调用你们所做的反应,比如update方法。其他辅助的可能还需要删除注册信息等。
PHP5中提供了观察者和与被观察者的借口。
可以参考博文http://www.cnblogs.com/baochuan/archive/2012/02/22/2362668.html和http://www.phpddt.com/php/observer.html
<?php //被观察者借口 Interface isObserver{ function attach($sub);//添加观察者 function del($sub);//踢除观察者 function donotify();//通知观察者 } class Weight implements isObserver{ private $observers=array(); public function attach($sub){ $this->observers[]=$sub; } public function del($sub){ $key=array_search($sub,$this->observers); if($key!=="false"){ unset($this->observers[$key]); } } public function donotify(){ foreach($this->observers as $value){ $value->update(); } } } //观察者的借口定义 Interface Observer{ function update(); } class realObserver implements Observer{ public function update(){ echo "I know the chang"; } } $w=new Weight(); $w->attach(new realObserver()); $w->donotify();
四、责任链模式
联想现实场景,比如一级一级上报,请假,先给组长,不在组长职权范围就给班长,不在班长职权范围就上班班主任。再比如请假。下面我写了一个地区判断。
应用在:对于一个处理有多个同等的对象处理,具体哪个对象处理根据处理的情况定。
参看博文:http://blog.csdn.net/jhq0113/article/details/46454419
<?php header('content-type:text/html;charset=utf-8'); class Location{ public $zone; public function __construct($zone){ $this->zone=$zone; } } //抽象判断接口 abstract class world{ public $follow; abstract function judge($sub); //自己的下一个处理者 function setNext($sub){ $this->follow=$sub; } } class europe extends world{ public function judge($sub){ if($sub->zone=="europe"){ echo "来自欧洲"; }else{ if(isset($this->follow)){ $this->follow->judge($sub); } } } } class asia extends world{ public function judge($sub){ if($sub->zone=="asia"){ echo "来自亚洲"; }else{ if(isset($this->follow)){ $this->follow->judge($sub); } } } } class africa extends world{ public function judge($sub){ if($sub->zone=="africa"){ echo "来自非洲"; }else{ if(isset($this->follow)){ $this->follow->judge($sub); } } } } $l=new Location("asia"); $ouzhou=new europe(); $yazhou=new asia(); $feizhou=new africa(); $ouzhou->setNext($yazhou); $yazhou->setNext($feizhou); $ouzhou->judge($l);
五、策略模式
理解:从名称上理解就是不同的方法,比如出行的策略有,步行,公交,地铁等,目的相同,过程有差异。
由三部分组成,用术语就是策略模式的三种角色:
抽象策略(Strategy)角色:定义所有支持的算法的公共接口。通常是以一个接口或抽象来实现。
具体策略(ConcreteStrategy)角色:以Strategy接口实现某具体算法
环境(Context)角色:持有一个Strategy类的引用,用一个ConcreteStrategy对象来配置
实现步骤:
1.定义抽象角色类(定义好各个实现的共同抽象方法)
2.定义具体策略类(具体实现父类的共同方法)
3.定义环境角色类(私有化申明抽象角色变量,重载构造方法,执行抽象方法)
我个人感觉重要的一点是,最后执行了抽象方法
参考博文http://www.phpddt.com/php/strategy.html和http://www.cnblogs.com/yangjinjin/archive/2013/01/31/2887498.html
<?php header('content-type:text/html;charset=utf-8'); //抽象公共类 abstract class method{ abstract function show(); } class walk extends method{ public function show(){ echo "走路"; } } class bus extends method{ public function show(){ echo "乘公交"; } } class trans extends method{ public function show(){ echo "乘地铁"; } } class choose{ public function get($obj){ return $obj->show(); } } $ch=new choose(); echo $ch->get(new bus());
六、装饰模式
角色:
Component(被装饰对象基类)
ConcreteComponent(具体被装饰对象)
Decorator(装饰者基类)
ContreteDecorator(具体的装饰者类)
其中具体被装饰对象和装饰者基类都需要继承被装饰对象基类
参考http://www.phpddt.com/php/design-decoration.html和http://www.open-open.com/lib/view/open1456127388011.html
<?php header('content-type:text/html;charset=utf-8'); //被装饰者基类 abstract class Area{ abstract function treasure(); } //装饰者基类 abstract class AreaDecorateor extends Area{ protected $_area = null; public function __construct(Area $area) { $this->_area = $area; } } //具体被装饰者类 class Forest extends Area { public function treasure() { return 100; } } //具体装饰类A class DecoratorA extends AreaDecorateor{ public function __construct(Area $area) { parent::__construct($area); } public function treasure() { return $this->_area->treasure().'Add Operation A '.PHP_EOL; } } //具体装饰类B class DecoratorB extends AreaDecorateor{ public function __construct(Area $area) { parent::__construct($area); } public function treasure() { return $this->_area->treasure().'Add Operation B '.PHP_EOL; } } $da=new DecoratorA(new Forest()); echo $da->treasure(); $db=new DecoratorB(new Forest()); echo $db->treasure(); $dba=new DecoratorB($da); echo $dba->treasure();
七、适配器模式
将一个类的接口转换成客户希望的另外一个接口
参考博文http://www.cnblogs.com/whoamme/p/3324325.html
<?php //目标角色 interface Target { public function say(); public function dance(); } //源角色 class Adaptee { public function say(){ echo 'hello world'."<br>"; } } //类适配器角色 class Adapter implements Target { private $adaptee; function __construct(Adaptee $adaptee) { $this->adaptee = $adaptee; } //调用Adaptee的方法 public function say(){ echo $this->adaptee->say(); } public function dance(){ echo 'dance'."<br>"; } } //客户端 class Client { public static function main() { $adaptee = new Adaptee(); $adapter = new Adapter($adaptee); $adapter->say(); $adapter->dance(); } } Client::main();
八、桥接模式
两个维度处理,比如以短信,邮件,电话方式发信息,信息分为普通,快,紧急三种。
参考博文http://blog.csdn.net/jhq0113/article/details/45441793
<?php header('content-type:text/html;charset=utf-8'); //信息抽象类 abstract class info{ public $type; public function __construct($obj){ $this->type=$obj; } abstract function msg($content); public function fasong($to,$content){ $data=$this->msg($content); return $this->type->send($to,$data); } } class phone{ public function send($to,$content){ return "手机".$to.$content; } } class email{ public function send($to,$content){ return "邮件".$to.$content; } } class putong extends info{ public function msg($content){ return "普遍".$content; } } class speed extends info{ public function msg($content){ return "加急".$content; } } $s=new speed(new phone()); echo $s->fasong("张三","祝身体健康");
结果
手机张三加急祝身体健康