PK憃Hmeta.xml(1112287#F3F4F9XMind3.5.3.201506230006PKպ-(PK憃H content.xmlq设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct); 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例 <?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。 <?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求Q 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能<?php/** * 手机软件 */abstract class PhoneSoft{ public function run(){}}<?php/** * 手机游戏 */class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; }}<?php/** * 手机通讯录 */class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; }}<?php/** * 手机品牌 */abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){}}<?php/** * 苹果 */class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}<?php/** * 诺基亚 */class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能 <?php /** * 手机软件 */ abstract class PhoneSoft{ public function run(){} } <?php /** * 手机游戏 */ class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; } } <?php /** * 手机通讯录 */ class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; } } <?php /** * 手机品牌 */ abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){} } <?php /** * 苹果 */ class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } <?php /** * 诺基亚 */ class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } 组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }享元模式<Ylabels>享元模式: 运用共享技术有效的支持大量细粒度的对象 享元模式变化的是对象的存储开销享元模式中主要角色: 抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外运状态的操作可以通过调用商业以参数形式传入 具体享元(ConcreteFlyweight)角色:实现Flyweight接口,并为内部状态(如果有的话)拉回存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的 不共享的具体享元(UnsharedConcreteFlyweight)角色:并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能,但它并不强制共享享元工厂(FlyweightFactory)角色:负责创建和管理享元角色。本角色必须保证享元对象可能被系统适当地共享 客户端(Client)角色:本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态享元模式的优点: Flyweight模式可以大幅度地降低内存中对象的数量享元模式的缺点: Flyweight模式使得系统更加复杂 Flyweight模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长享元模式适用场景:当一下情况成立时使用Flyweight模式: 1 一个应用程序使用了大量的对象 2 完全由于使用大量的对象,造成很大的存储开销 3 对象的大多数状态都可变为外部状态 4 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象 5 应用程序不依赖于对象标识享元模式与其它模式: 单例模式(Singleton):客户端要引用享元对象,是通过工厂对象创建或者获得的,客户端每次引用一个享元对象,都是可以通过同一个工厂对象来引用所需要的享元对象。因此,可以将享元工厂设计成单例模式,这样就可以保证客户端只引用一个工厂实例。因为所有的享元对象都是由一个工厂对象统一管理的,所以在客户端没有必要引用多个工厂对象。不管是单纯享元模式还是复合享元模式中的享元工厂角色,都可以设计成为单例模式,对于结果是不会有任何影响的。 Composite模式:复合享元模式实际上是单纯享元模式与合成模式的组合。单纯享元对象可以作为树叶对象来讲,是可以共享的,而复合享元对象可以作为树枝对象,因此在复合享元角色中可以添加聚集管理方法<?php/** * 抽象享元角色 */abstract class Flyweight{ abstract public function operation($state);}<?php /** * 具体享元角色 */class ConcreteFlyweight extends Flyweight{ private $_intrinsicState = null; /** * @param $state 内部状态 */ public function __construct($state){ $this->_intrinsicState = $state; } public function operation($state) { echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; }}<?php/** * 不共享的具体享元,客户端直接调用 */class UnsharedConcreteFlyweight extends Flyweight { private $_intrinsicState = null; /** * 构造方法 * @param string $state 内部状态 */ public function __construct($state) { $this->_intrinsicState = $state; } public function operation($state) { echo 'UnsharedConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } }<?php /** * 享元工厂角色 */class FlyweightFactory{ private $_flyweights; public function __construct(){ $this->_flyweights = array(); } public function getFlyweight($state){ if(isset($this->_flyweights[$state])){ return $this->_flyweights[$state]; } return $this->_flyweights[$state] = new ConcreteFlyweight($state); }} /** * 享元模式 */ public function actionFlyweight(){ Yii::import('ext.flyweight.*'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state A'); $flyweightFactory->operation('other state A'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state B'); $flyweightFactory->operation('other state B'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state C'); $flyweightFactory->operation('other state C'); /* 不共享的对象,单独调用 */ $uflyweight = new UnsharedConcreteFlyweight('state A'); $uflyweight->operation('other state A'); }享元模式: 运用共享技术有效的支持大量细粒度的对象 享元模式变化的是对象的存储开销 享元模式中主要角色: 抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外运状态的操作可以通过调用商业以参数形式传入 具体享元(ConcreteFlyweight)角色:实现Flyweight接口,并为内部状态(如果有的话)拉回存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的 不共享的具体享元(UnsharedConcreteFlyweight)角色:并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能,但它并不强制共享 享元工厂(FlyweightFactory)角色:负责创建和管理享元角色。本角色必须保证享元对象可能被系统适当地共享 客户端(Client)角色:本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态 享元模式的优点: Flyweight模式可以大幅度地降低内存中对象的数量 享元模式的缺点: Flyweight模式使得系统更加复杂 Flyweight模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长 享元模式适用场景: 当一下情况成立时使用Flyweight模式: 1 一个应用程序使用了大量的对象 2 完全由于使用大量的对象,造成很大的存储开销 3 对象的大多数状态都可变为外部状态 4 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象 5 应用程序不依赖于对象标识 享元模式与其它模式: 单例模式(Singleton):客户端要引用享元对象,是通过工厂对象创建或者获得的,客户端每次引用一个享元对象,都是可以通过同一个工厂对象来引用所需要的享元对象。因此,可以将享元工厂设计成单例模式,这样就可以保证客户端只引用一个工厂实例。因为所有的享元对象都是由一个工厂对象统一管理的,所以在客户端没有必要引用多个工厂对象。不管是单纯享元模式还是复合享元模式中的享元工厂角色,都可以设计成为单例模式,对于结果是不会有任何影响的。 Composite模式:复合享元模式实际上是单纯享元模式与合成模式的组合。单纯享元对象可以作为树叶对象来讲,是可以共享的,而复合享元对象可以作为树枝对象,因此在复合享元角色中可以添加聚集管理方法 <?php /** * 抽象享元角色 */ abstract class Flyweight{ abstract public function operation($state); } <?php /** * 具体享元角色 */ class ConcreteFlyweight extends Flyweight{ private $_intrinsicState = null; /** * @param $state 内部状态 */ public function __construct($state){ $this->_intrinsicState = $state; } public function operation($state) { echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } } <?php /** * 不共享的具体享元,客户端直接调用 */ class UnsharedConcreteFlyweight extends Flyweight { private $_intrinsicState = null; /** * 构造方法 * @param string $state 内部状态 */ public function __construct($state) { $this->_intrinsicState = $state; } public function operation($state) { echo 'UnsharedConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } } <?php /** * 享元工厂角色 */ class FlyweightFactory{ private $_flyweights; public function __construct(){ $this->_flyweights = array(); } public function getFlyweight($state){ if(isset($this->_flyweights[$state])){ return $this->_flyweights[$state]; } return $this->_flyweights[$state] = new ConcreteFlyweight($state); } } /** * 享元模式 */ public function actionFlyweight(){ Yii::import('ext.flyweight.*'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state A'); $flyweightFactory->operation('other state A'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state B'); $flyweightFactory->operation('other state B'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state C'); $flyweightFactory->operation('other state C'); /* 不共享的对象,单独调用 */ $uflyweight = new UnsharedConcreteFlyweight('state A'); $uflyweight->operation('other state A'); }代理模式代理模式: 为其他对象提供一种代理以控制对这个对象的访问代理模式使用场合: 第一种:远程代理,就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实 第二种:虚拟代理,·根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象 第三种:安全代理,用来控制真实对象访问时的权限 第四种:智能指引,是指当调用真实的对象时,代理处理另外一些事代码实例: 追求者想送被追求人花,但是害羞派朋友送,朋友就是代理<?php /** * 代理模式 * 接口类 */interface IGiveGift{ public function giveDolls(); public function giveFlowers(); public function giveChocolate();}<?php/** * 追求者 * 实现送礼物接口 */class Pursuit implements IGiveGift{ public $mm; public function __construct($mm){ $this->mm = $mm; } public function giveDolls(){ echo $this->mm .'送你娃娃'; } public function giveFlowers(){ echo $this->mm .'送你花'; } public function giveChocolate(){ echo $this->mm .'送你巧克力'; }}<?php /** * 追求者的朋友 * 真正的代理 */class Proxy implements IGiveGift{ public $pursuit; public function __construct($mm){ $this->pursuit = new Pursuit($mm); } public function giveDolls(){ $this->pursuit->giveDolls(); } public function giveFlowers(){ $this->pursuit->giveFlowers(); } public function giveChocolate(){ $this->pursuit->giveChocolate(); }} /** * 代理模式 */ public function actionProxy(){ Yii::import('ext.proxy.*'); $proxy = new Proxy('娇娇'); $proxy->giveDolls(); $proxy->giveFlowers(); $proxy->giveChocolate(); }代理模式: 为其他对象提供一种代理以控制对这个对象的访问 代理模式使用场合: 第一种:远程代理,就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实 第二种:虚拟代理,·根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象 第三种:安全代理,用来控制真实对象访问时的权限 第四种:智能指引,是指当调用真实的对象时,代理处理另外一些事 代码实例: 追求者想送被追求人花,但是害羞派朋友送,朋友就是代理 <?php /** * 代理模式 * 接口类 */ interface IGiveGift{ public function giveDolls(); public function giveFlowers(); public function giveChocolate(); } <?php /** * 追求者 * 实现送礼物接口 */ class Pursuit implements IGiveGift{ public $mm; public function __construct($mm){ $this->mm = $mm; } public function giveDolls(){ echo $this->mm .'送你娃娃'; } public function giveFlowers(){ echo $this->mm .'送你花'; } public function giveChocolate(){ echo $this->mm .'送你巧克力'; } } <?php /** * 追求者的朋友 * 真正的代理 */ class Proxy implements IGiveGift{ public $pursuit; public function __construct($mm){ $this->pursuit = new Pursuit($mm); } public function giveDolls(){ $this->pursuit->giveDolls(); } public function giveFlowers(){ $this->pursuit->giveFlowers(); } public function giveChocolate(){ $this->pursuit->giveChocolate(); } } /** * 代理模式 */ public function actionProxy(){ Yii::import('ext.proxy.*'); $proxy = new Proxy('娇娇'); $proxy->giveDolls(); $proxy->giveFlowers(); $proxy->giveChocolate(); }行为型模式2访问者模式访问者模式: 表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素的类的前提下定义作用于这些元素的新操作<?php/** * 访问者模式 */abstract class Visitor{ abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element);}<?phpclass ConcreteVisitor1 extends Visitor{ public function visitCroncreteElementA($element) { echo get_class($element)." visit 1A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 1B<br/>"; }}<?phpclass ConcreteVisitor2 extends Visitor{ public function visitCroncreteElementA($element) { echo get_class($element)." visit 2A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 2B<br/>"; }}<?phpabstract class Element{abstract public function accept($visitor);}<?phpclass ObjectStructure{ private $_elements = array(); public function attach($element) { $this->_elements[] = $element; } public function detach($element) { if($key = array_search($element,$this->_elements) !== false) unset($this->_elements[$key]); } public function accept($visitor) { foreach($this->_elements as $element) { $element->accept($visitor); } }} /** *访问者模式 */ public function actionVisitor(){ Yii::import('ext.visitor.*'); $objOS = new ObjectStructure(); $objOS->attach(new ConcreteElementA()); $objOS->attach(new ConcreteElementB()); $objCV1 = new ConcreteVisitor1(); $objCV2 = new ConcreteVisitor2(); $objOS->accept($objCV1); $objOS->accept($objCV2); }访问者模式: 表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素的类的前提下定义作用于这些元素的新操作 <?php /** * 访问者模式 */ abstract class Visitor { abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element); } <?php class ConcreteVisitor1 extends Visitor { public function visitCroncreteElementA($element) { echo get_class($element)." visit 1A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 1B<br/>"; } } <?php class ConcreteVisitor2 extends Visitor { public function visitCroncreteElementA($element) { echo get_class($element)." visit 2A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 2B<br/>"; } } <?php abstract class Element { abstract public function accept($visitor); } <?php class ObjectStructure { private $_elements = array(); public function attach($element) { $this->_elements[] = $element; } public function detach($element) { if($key = array_search($element,$this->_elements) !== false) unset($this->_elements[$key]); } public function accept($visitor) { foreach($this->_elements as $element) { $element->accept($visitor); } } } /** *访问者模式 */ public function actionVisitor(){ Yii::import('ext.visitor.*'); $objOS = new ObjectStructure(); $objOS->attach(new ConcreteElementA()); $objOS->attach(new ConcreteElementB()); $objCV1 = new ConcreteVisitor1(); $objCV2 = new ConcreteVisitor2(); $objOS->accept($objCV1); $objOS->accept($objCV2); }中介者模式中介者模式: 用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用从而使其耦合松散,而且可以独立地改变它们之间的交互<?php/** * 中介者模式 * 中介者抽象基类 */abstract class Mediator{ public function send($message, $colleague){ }}<?php/** * 同事基类 * 用于同事之间发送信息 */abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){}}<?php/** * 具体中介者 */class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; }}<?php/** * 具体同事类 * */class ColleagueA extends Colleague{ /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; }}<?php/** * 具体同事类 * */class ColleagueB extends Colleague{ public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; }}/** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); }中介者模式: 用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用从而使其耦合松散,而且可以独立地改变它们之间的交互 <?php /** * 中介者模式 * 中介者抽象基类 */ abstract class Mediator{ public function send($message, $colleague){ } } <?php /** * 同事基类 * 用于同事之间发送信息 */ abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){} } <?php /** * 具体中介者 */ class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; } } <?php /** * 具体同事类 * */ class ColleagueA extends Colleague { /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; } } <?php /** * 具体同事类 * */ class ColleagueB extends Colleague { public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; } } /** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } 解释器模式解释器模式: 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子 解释器模式的优缺点: 解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。 但是,解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。同时,由于采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。结构图:代码实例:<?phpclass Expression{ function interpreter($str) { return $str; }}<?phpclass ExpressionNum extends Expression{ function interpreter($str) { switch($str) { case "0": return "零"; case "1": return "一"; case "2": return "二"; case "3": return "三"; case "4": return "四"; case "5": return "五"; case "6": return "六"; case "7": return "七"; case "8": return "八"; case "9": return "九"; } }} <?phpclass ExpressionCharater extends Expression{ function interpreter($str) { return strtoupper($str); }}<?phpclass Interpreter{ function execute($string) { $expression = null; for($i = 0;$i<strlen($string);$i++) { $temp = $string[$i]; switch(true) { case is_numeric($temp): $expression = new ExpressionNum(); break; default: $expression = new ExpressionCharater(); break; } echo $expression->interpreter($temp); } }} /** *解释器模式 */ public function actionExpression(){ Yii::import('ext.expression.*'); $obj = new Interpreter(); $obj->execute("12345abc"); }解释器模式: 给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子 解释器模式的优缺点: 解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。 但是,解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。同时,由于采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。 结构图: 代码实例: <?php class Expression { function interpreter($str) { return $str; } } <?php class ExpressionNum extends Expression { function interpreter($str) { switch($str) { case "0": return "零"; case "1": return "一"; case "2": return "二"; case "3": return "三"; case "4": return "四"; case "5": return "五"; case "6": return "六"; case "7": return "七"; case "8": return "八"; case "9": return "九"; } } } <?php class ExpressionCharater extends Expression { function interpreter($str) { return strtoupper($str); } } <?php class Interpreter { function execute($string) { $expression = null; for($i = 0;$i<strlen($string);$i++) { $temp = $string[$i]; switch(true) { case is_numeric($temp): $expression = new ExpressionNum(); break; default: $expression = new ExpressionCharater(); break; } echo $expression->interpreter($temp); } } } /** *解释器模式 */ public function actionExpression(){ Yii::import('ext.expression.*'); $obj = new Interpreter(); $obj->execute("12345abc"); } 策略模式策略模式: 定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户封装: 把行为用接口封装起来,我们可以把那些经常变化的部分,从当前的类中取出来,用接口进行单独的封装。 互相替换:我们封装好了接口,通过指定不同的接口实现类进行算法的变化。<?php/** * 策略模式接口 * */interface FlyBehavior{ public function fly();}<?php/** *用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */class FlyWithWings implements FlyBehavior{ /** *飞行方法 * */ public function fly(){ echo 'fly with wings'; }}<?php/** *不用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */class FlyWithNo implements FlyBehavior{ /** *飞行方法 */ public function fly(){ echo 'fly with no'; }}<?php/** *鸭子类 *@author li.yonghuan *@version 2014.01.17 */class Duck{ /** *飞行实例 *@var FlyBehavior object */ private $_flyBehavior; /** *开始飞 * */ public function performFly(){ $this->_flyBehavior->fly(); } /** *设置飞行实例 *@param $behavior Flybehavior */ public function setFlyBehavior( FlyBehavior $behavior ){ $this->_flyBehavior = $behavior; }}<?php/** *橡皮鸭 *@author li.yonghuan *@version 2014.01.17 */ class RubberDuck extends Duck{ } /** * 策略模式 */ public function actionStrategy(){ Yii::import('ext.strategy.*'); $duck = new RubberDuck(); /* 橡皮鸭用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 橡皮鸭不用翅膀飞行 */ $duck->setFlyBehavior( new FlyWithNo() ); $duck->performFly(); }策略模式: 定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户 封装: 把行为用接口封装起来,我们可以把那些经常变化的部分,从当前的类中取出来,用接口进行单独的封装。 互相替换:我们封装好了接口,通过指定不同的接口实现类进行算法的变化。 <?php /** * 策略模式接口 * */ interface FlyBehavior{ public function fly(); } <?php /** *用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */ class FlyWithWings implements FlyBehavior{ /** *飞行方法 * */ public function fly(){ echo 'fly with wings'; } } <?php /** *不用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */ class FlyWithNo implements FlyBehavior{ /** *飞行方法 */ public function fly(){ echo 'fly with no'; } } <?php /** *鸭子类 *@author li.yonghuan *@version 2014.01.17 */ class Duck{ /** *飞行实例 *@var FlyBehavior object */ private $_flyBehavior; /** *开始飞 * */ public function performFly(){ $this->_flyBehavior->fly(); } /** *设置飞行实例 *@param $behavior Flybehavior */ public function setFlyBehavior( FlyBehavior $behavior ){ $this->_flyBehavior = $behavior; } } <?php /** *橡皮鸭 *@author li.yonghuan *@version 2014.01.17 */ class RubberDuck extends Duck{ } /** * 策略模式 */ public function actionStrategy(){ Yii::import('ext.strategy.*'); $duck = new RubberDuck(); /* 橡皮鸭用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 橡皮鸭不用翅膀飞行 */ $duck->setFlyBehavior( new FlyWithNo() ); $duck->performFly(); }备忘录模式备忘录模式: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可将该对象恢复到原先保存的状态代码实例:<?php/** * 发起人角色 */class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); } public function show(){ echo "<br/>State=".$this->state; }}<?php/** * 备忘录角色 */class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; }}<?php/** * 管理角色 */class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; }} /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); }备忘录模式: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可将该对象恢复到原先保存的状态 代码实例: <?php /** * 发起人角色 */ class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); } public function show(){ echo "<br/>State=".$this->state; } } <?php /** * 备忘录角色 */ class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; } } <?php /** * 管理角色 */ class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; } } /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); } 迭代器模式迭代器模式: 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示代码实例: 公交买票<?php /** * 迭代器抽象类 */abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem();}?><?php /** * 具体迭代器类 */class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; }}<?php /** * 聚集抽象类 */abstract class Aggregate{ abstract public function createIterator();}<?php /** * 具体聚集类 */class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } }?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }迭代器模式: 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示 代码实例: 公交买票 <?php /** * 迭代器抽象类 */ abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem(); } ?> <?php /** * 具体迭代器类 */ class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; } } <?php /** * 聚集抽象类 */ abstract class Aggregate{ abstract public function createIterator(); } <?php /** * 具体聚集类 */ class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } } ?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }行为型模式1命令模式命令模式: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分开,委派 给不同的对象。 请求的一方发出请求要求执行一个操作;接受的一方受到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收的一方的接口,更 不必知道请求是怎么被接收的,以及操作是否被执行、何时被执行,以及是怎么被执行的。 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法, 负责调用接收者的相应操作。Execute()方法通常叫做执行方法。 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者, 实施和执行请求的方法叫做行动方法。<?php/** *命令接口 */interface Command{ public function execute();}<?php/** *接受者 */class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; }}<?php/** *具体命令 */class ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); }}<?php/** *请求者 */class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); }} /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }命令模式: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分开,委派 给不同的对象。 请求的一方发出请求要求执行一个操作;接受的一方受到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收的一方的接口,更 不必知道请求是怎么被接收的,以及操作是否被执行、何时被执行,以及是怎么被执行的。 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法, 负责调用接收者的相应操作。Execute()方法通常叫做执行方法。 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者, 实施和执行请求的方法叫做行动方法。 <?php /** *命令接口 */ interface Command{ public function execute(); } <?php /** *接受者 */ class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; } } <?php /** *具体命令 */ qclass ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); } } <?php /** *请求者 */ class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); } } /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }观察者模式观察者模式: 观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象(主体)的状态发生改变时,所有依赖它的对象(观察者)都得到通知并自动更新。 它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主题感兴趣的依赖项(观察者)列表。让所有观察者各自实现公共的Observer接口,以取消主体和依赖项的直接依赖关系。<?php/** * 主题功能 */class Observable{ /** * 添加观察者 */ function attact (Observer $observer); /** * 删除观察者 */ function detach (Observer $observer); /** * 通知观察者 */ function notify ();}<?php/** * 主体类 * 被观察者 */class Login implements Observable{ /** *密码错误状态 */ const LOGIN_ACCESS = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_USER_UNKNOWN = 3; /** *登录时的状态 * */ private $loginstatus; /** *观察者列表 *@var array */ private $observers; /** *构造方法 * */ public function __construct(){ $this->observers = array(); } /** *添加观察者 *@param $observer Observer object */ public function attach( Observer $observer ){ $this->observers[] = $observer; } /** *删除观察者 *@param $observer Observer object */ public function detach( Observer $observer ){ $newobservers = array(); foreach( $this->observers as $obs ){ if( $obs != $observer ){ $newobservers[] = $observer; } } $this->observers = $newobservers; } /** *通知观察者 * */ public function notify(){ foreach( $this->observers as $obs ){ $obs->update( $this ); } } /** *处理登录 *@param $user string 用户名 *@param $pass string 密码 *@param $ip string IP地址 */ public function handleLogin( $user='li.yonghuan', $pass='123456', $ip='127.0.0.1' ) { switch( rand(1,3) ) { case 1: $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); $ret = true; break; case 2: $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); $ret = false; break; case 3: $this->setStatus( self::LOGIN_USER_UNKNOWN, $user, $ip ); $ret = false; break; } $this->notify(); return $ret; } /** *设置状态值 *@param $status string 状态值 *@param $user string 用户名 *@param $ip string IP地址 */ public function setStatus( $status, $user, $ip ) { $this->loginstatus = array( $status, $user, $ip ); } /** *获取状态 *登录时产生的各种状态 */ public function getStatus() { return $this->loginstatus; } }<?php/** *接口:观察者 *@author li.yonghuan *@version 2014.01.18 * */interface Observer { /** *更新 */ function update( Observable $observable );}<?php/** *抽象类,登录观察者 *@author li.yonghuan *@version 2014.01.18 * */abstract class LoginObserver implements Observer { /** *Login 对象 *@var Login object */ private $login; /** *构造方法 *@param $login Login object */ public function __construct( Login $login ) { $this->login = $login; $login->attach( $this ); } /** *更新操作 *@param $observer Observer */ public function update( Observable $observable ) { if( $observable === $this->login ) { $this->doUpdate( $observable ); } } /** *执行更新 *@param login Login */ abstract function doUpdate( Login $login ); } <?php/** *安全监控登录,负责登录安全的观察者 *@author li.yonghuan *@version 2014.01.18 */class SecurityMonitor extends LoginObserver { /** *执行更新 *@param $login Login */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_WRONG_PASS ) { //发送邮件给系统管理员 print __CLASS__.":\tsending mail to sysadmin"; } }} <?php/** *正确登录,观察者 *@author li.yonghuan *@version 2014.01.18 */class GeneralLogger extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_ACCESS ) { //记录登录数据到日志 print __CLASS__.":\tadd login data to log"; } }} <?php/** *用户名错误,观察者 *@author li.yonghuan *@version 2014.01.18 */class UserMonitor extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_USER_UNKNOWN ) { //用户名错误 print __CLASS__.":\tusername is uncorrect"; } }} /** * 观察者模式 */ public function actionObserver(){ Yii::import('ext.observer.*'); $login = new Login(); //添加安全观察者 $login->attach(new SecurityMonitor( $login )); //添加正确登录观察者 $login->attach(new GeneralLogger( $login )); //添加用户名观察者 $login->attach(new UserMonitor( $login )); $login->handleLogin(); }观察者模式: 观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象(主体)的状态发生改变时,所有依赖它的对象(观察者)都得到通知并自动更新。 它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主题感兴趣的依赖项(观察者)列表。让所有观察者各自实现公共的Observer接口,以取消主体和依赖项的直接依赖关系。 <?php /** * 主题功能 */ class Observable{ /** * 添加观察者 */ function attact (Observer $observer); /** * 删除观察者 */ function detach (Observer $observer); /** * 通知观察者 */ function notify (); } <?php /** * 主体类 * 被观察者 */ class Login implements Observable{ /** *密码错误状态 */ const LOGIN_ACCESS = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_USER_UNKNOWN = 3; /** *登录时的状态 * */ private $loginstatus; /** *观察者列表 *@var array */ private $observers; /** *构造方法 * */ public function __construct(){ $this->observers = array(); } /** *添加观察者 *@param $observer Observer object */ public function attach( Observer $observer ){ $this->observers[] = $observer; } /** *删除观察者 *@param $observer Observer object */ public function detach( Observer $observer ){ $newobservers = array(); foreach( $this->observers as $obs ){ if( $obs != $observer ){ $newobservers[] = $observer; } } $this->observers = $newobservers; } /** *通知观察者 * */ public function notify(){ foreach( $this->observers as $obs ){ $obs->update( $this ); } } /** *处理登录 *@param $user string 用户名 *@param $pass string 密码 *@param $ip string IP地址 */ public function handleLogin( $user='li.yonghuan', $pass='123456', $ip='127.0.0.1' ) { switch( rand(1,3) ) { case 1: $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); $ret = true; break; case 2: $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); $ret = false; break; case 3: $this->setStatus( self::LOGIN_USER_UNKNOWN, $user, $ip ); $ret = false; break; } $this->notify(); return $ret; } /** *设置状态值 *@param $status string 状态值 *@param $user string 用户名 *@param $ip string IP地址 */ public function setStatus( $status, $user, $ip ) { $this->loginstatus = array( $status, $user, $ip ); } /** *获取状态 *登录时产生的各种状态 */ public function getStatus() { return $this->loginstatus; } } <?php /** *接口:观察者 *@author li.yonghuan *@version 2014.01.18 * */ interface Observer { /** *更新 */ function update( Observable $observable ); } <?php /** *抽象类,登录观察者 *@author li.yonghuan *@version 2014.01.18 * */ abstract class LoginObserver implements Observer { /** *Login 对象 *@var Login object */ private $login; /** *构造方法 *@param $login Login object */ public function __construct( Login $login ) { $this->login = $login; $login->attach( $this ); } /** *更新操作 *@param $observer Observer */ public function update( Observable $observable ) { if( $observable === $this->login ) { $this->doUpdate( $observable ); } } /** *执行更新 *@param login Login */ abstract function doUpdate( Login $login ); } <?php /** *安全监控登录,负责登录安全的观察者 *@author li.yonghuan *@version 2014.01.18 */ class SecurityMonitor extends LoginObserver { /** *执行更新 *@param $login Login */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_WRONG_PASS ) { //发送邮件给系统管理员 print __CLASS__.":\tsending mail to sysadmin"; } } } <?php /** *正确登录,观察者 *@author li.yonghuan *@version 2014.01.18 */ class GeneralLogger extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_ACCESS ) { //记录登录数据到日志 print __CLASS__.":\tadd login data to log"; } } } <?php /** *用户名错误,观察者 *@author li.yonghuan *@version 2014.01.18 */ class UserMonitor extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_USER_UNKNOWN ) { //用户名错误 print __CLASS__.":\tusername is uncorrect"; } } } /** * 观察者模式 */ public function actionObserver(){ Yii::import('ext.observer.*'); $login = new Login(); //添加安全观察者 $login->attach(new SecurityMonitor( $login )); //添加正确登录观察者 $login->attach(new GeneralLogger( $login )); //添加用户名观察者 $login->attach(new UserMonitor( $login )); $login->handleLogin(); }模版模式模版模式: 定义一个操作的算法骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤<?php/** *模版模式基类 */abstract class Template{ public function templateA(){} public function templateB(){} public function getTemplate(){ $this->templateA(); $this->templateB(); }}<?php/** * 子类 */class TemplateChild extends Template{ public function templateA(){ echo 'A'; } public function templateB(){ echo 'B'; }} /** *模版方法 */ public function actionTemplate(){ Yii::import('ext.template.*'); $templateC = new TemplateChild; $templateC->getTemplate(); }模版模式: 定义一个操作的算法骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 <?php /** *模版模式基类 */ abstract class Template{ public function templateA(){} public function templateB(){} public function getTemplate(){ $this->templateA(); $this->templateB(); } } <?php /** * 子类 */ class TemplateChild extends Template{ public function templateA(){ echo 'A'; } public function templateB(){ echo 'B'; } } /** *模版方法 */ public function actionTemplate(){ Yii::import('ext.template.*'); $templateC = new TemplateChild; $templateC->getTemplate(); }职责链模式职责链模式: 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它<?php/** *职责链抽象类 */abstract class Chain{ public $chain; public function setChain($chain){ $this->chain = $chain; } public function handleRequest($request){}}<?php/** *职责链一号 *计算值是否为0 */class ChainZero extends Chain{ public function handleRequest($num){ if($num == 0){ echo '此数为0 职责链停止<br/>'; }else{ echo 'zero<br/>'; $this->chain->handleRequest($num); } }}<?php/** *职责链一号 *计算值是否为奇数 */class ChainEven extends Chain{ public function handleRequest($num){ if($num%2 == 1){ echo '此数为奇数 职责链停止<br/>'; }else{ echo 'even<br/>'; $this->chain->handleRequest($num); } }}<?php/** *职责链一号 *计算值是否为偶数 */class ChainOdd extends Chain{ public function handleRequest($num){ if($num%2 != 1){ echo '此数为偶数 职责链停止<br/>'; }else{ echo 'odd<br/>'; $this->chain->handleRequest($num); } }} /** *职责链模式 */ public function actionChain(){ Yii::import('ext.chain.*'); $chainZero = new ChainZero(); $chainEven = new ChainEven(); $chainOdd = new ChainOdd(); $chainZero->setChain($chainEven); $chainEven->setChain($chainOdd); foreach(array(2,3,4,5,0) as $num) { $chainZero->handleRequest($num); } }职责链模式: 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 <?php /** *职责链抽象类 */ abstract class Chain{ public $chain; public function setChain($chain){ $this->chain = $chain; } public function handleRequest($request){} } <?php /** *职责链一号 *计算值是否为0 */ class ChainZero extends Chain{ public function handleRequest($num){ if($num == 0){ echo '此数为0 职责链停止<br/>'; }else{ echo 'zero<br/>'; $this->chain->handleRequest($num); } } } <?php /** *职责链一号 *计算值是否为奇数 */ class ChainEven extends Chain{ public function handleRequest($num){ if($num%2 == 1){ echo '此数为奇数 职责链停止<br/>'; }else{ echo 'even<br/>'; $this->chain->handleRequest($num); } } } <?php /** *职责链一号 *计算值是否为偶数 */ class ChainOdd extends Chain{ public function handleRequest($num){ if($num%2 != 1){ echo '此数为偶数 职责链停止<br/>'; }else{ echo 'odd<br/>'; $this->chain->handleRequest($num); } } } /** *职责链模式 */ public function actionChain(){ Yii::import('ext.chain.*'); $chainZero = new ChainZero(); $chainEven = new ChainEven(); $chainOdd = new ChainOdd(); $chainZero->setChain($chainEven); $chainEven->setChain($chainOdd); foreach(array(2,3,4,5,0) as $num) { $chainZero->handleRequest($num); } }状态模式状态模式: 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类 状态state模式是GOF23种模式中的一种,和命令模式一样,也是一种行为模式。状态模式和命令模式相当像,一样是“接口—实现类”这种模式的应用,是面向接口编程原则的体现。 状态模式属于对象创建型模式,其意图是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了他的类。比较常见的例子是在一个表示网络连接的类TCPConnection,一个TCPConnection对象的状态处于若干不同的状态之一:连接已经建立(Established),正在监听,连接已经关闭(closed)。当一个TCPConnection对象收到其他对象的请求时,他根据自身的状态作出不同的反应。 例如:一个Open请求的结果依赖于该连接已关闭还是连接已建立状态。State模式描述了TCPConnection如何在每一种状态下表现出不同的行为。这一种模式的关键思想是引入了一个称为TCPState的抽象类表示网络的连接状态,TCPState类为各种表示不同的操作状态的字类声明了一个公共接口。TCPState的子类实现与特定的状态相关的行为。例如,TCPEstablished和TCPClosed类分别实现了特定于TCPConnection的连接已建立状态和连接已关闭状态的行为。 举例来说:一个人具有生气,高兴和抓狂等状态,在这些状态下做同一个事情可能会有不同的结果,一个人的心情可能在这三种状态中循环转变。使用一个moodState类表示一个人的心情,使用mad,Happy,Angry类代表不同的心情<?php/** * 状态接口基类 */interface State{ public function handle($state); public function display();}<?php/** * 不同的环境改变不同的状态 */class Context{ private $state = null; public function __construct($state){ $this->setState($state); } public function setState($state){ $this->state = $state; } public function request(){ $this->state->display(); $this->state->handle($this); }}<?php/** * 状态类A */class StateA implements State{ public function handle($context) { $context->setState(new StateB()); } public function display() { echo "state A<br/>"; } }<?php/** * 状态类B */class StateB implements State{ public function handle($context) { $context->setState(new StateC()); } public function display() { echo "state B<br/>"; }}<?php/** * 状态类C */class StateC implements State{ public function handle($context) { $context->|setState(new StateA()); } public function display() { echo "state C<br/>"; }} /** *状态模式 */ public function actionState(){ Yii::import('ext.state.*'); $objContext = new Context(new StateB()); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); }状态模式: 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类 状态state模式是GOF23种模式中的一种,和命令模式一样,也是一种行为模式。状态模式和命令模式相当像,一样是“接口—实现类”这种模式的应用,是面向接口编程原则的体现。 状态模式属于对象创建型模式,其意图是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了他的类。比较常见的例子是在一个表示网络连接的类TCPConnection,一个TCPConnection对象的状态处于若干不同的状态之一:连接已经建立(Established),正在监听,连接已经关闭(closed)。当一个TCPConnection对象收到其他对象的请求时,他根据自身的状态作出不同的反应。 例如:一个Open请求的结果依赖于该连接已关闭还是连接已建立状态。State模式描述了TCPConnection如何在每一种状态下表现出不同的行为。这一种模式的关键思想是引入了一个称为TCPState的抽象类表示网络的连接状态,TCPState类为各种表示不同的操作状态的字类声明了一个公共接口。TCPState的子类实现与特定的状态相关的行为。例如,TCPEstablished和TCPClosed类分别实现了特定于TCPConnection的连接已建立状态和连接已关闭状态的行为。 举例来说:一个人具有生气,高兴和抓狂等状态,在这些状态下做同一个事情可能会有不同的结果,一个人的心情可能在这三种状态中循环转变。使用一个moodState类表示一个人的心情,使用mad,Happy,Angry类代表不同的心情 <?php /** * 状态接口基类 */ interface State{ public function handle($state); public function display(); } <?php /** * 不同的环境改变不同的状态 */ class Context{ private $state = null; public function __construct($state){ $this->setState($state); } public function setState($state){ $this->state = $state; } public function request(){ $this->state->display(); $this->state->handle($this); } } <?php /** * 状态类A */ class StateA implements State{ public function handle($context) { $context->setState(new StateB()); } public function display() { echo "state A<br/>"; } } <?php /** * 状态类B */ class StateB implements State{ public function handle($context) { $context->setState(new StateC()); } public function display() { echo "state B<br/>"; } } <?php /** * 状态类C */ class StateC implements State{ public function handle($context) { $context->setState(new StateA()); } public function display() { echo "state C<br/>"; } } /** *状态模式 */ public function actionState(){ Yii::import('ext.state.*'); $objContext = new Context(new StateB()); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); }自由主题画布 1建造者模式class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct);画布 2单例模式<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}<?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 画布 3原型模式<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }<?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }画布 4工厂方法<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }<?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; } 画布 6抽象工厂模式代码以后上传代码以后上传 画布 7原型模式<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }<?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }画布 7装饰模式案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); } 画布 8外观模式<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); }<?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 画布 9组合模式<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }<?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 画布 10适配器模式<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}<?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 画布 11桥接模式<?php/** * 手机软件 */abstract class PhoneSoft{ public function run(){}}<?php/** * 手机游戏 */class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; }}<?php/** * 手机通讯录 */class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; }}<?php/** * 手机品牌 */abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){}}<?php/** * 苹果 */class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}<?php/** * 诺基亚 */class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }} <?php /** * 手机软件 */ abstract class PhoneSoft{ public function run(){} } <?php /** * 手机游戏 */ class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; } } <?php /** * 手机通讯录 */ class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; } } <?php /** * 手机品牌 */ abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){} } <?php /** * 苹果 */ class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } <?php /** * 诺基亚 */ class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } 画布 12命令模式<?php/** *命令接口 */interface Command{ public function execute();}<?php/** *接受者 */class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; }}<?php/** *具体命令 */class ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); }}<?php/** *请求者 */class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); }} /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }<?php /** *命令接口 */ interface Command{ public function execute(); } <?php /** *接受者 */ class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; } } <?php /** *具体命令 */ class ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); } } <?php /** *请求者 */ class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); } } /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }画布 13观察者模式<?php/** * 主题功能 */class Observable{ /** * 添加观察者 */ function attact (Observer $observer); /** * 删除观察者 */ function detach (Observer $observer); /** * 通知观察者 */ function notify ();}<?php/** * 主体类 * 被观察者 */class Login implements Observable{ /** *密码错误状态 */ const LOGIN_ACCESS = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_USER_UNKNOWN = 3; /** *登录时的状态 * */ private $loginstatus; /** *观察者列表 *@var array */ private $observers; /** *构造方法 * */ public function __construct(){ $this->observers = array(); } /** *添加观察者 *@param $observer Observer object */ public function attach( Observer $observer ){ $this->observers[] = $observer; } /** *删除观察者 *@param $observer Observer object */ public function detach( Observer $observer ){ $newobservers = array(); foreach( $this->observers as $obs ){ if( $obs != $observer ){ $newobservers[] = $observer; } } $this->observers = $newobservers; } /** *通知观察者 * */ public function notify(){ foreach( $this->observers as $obs ){ $obs->update( $this ); } } /** *处理登录 *@param $user string 用户名 *@param $pass string 密码 *@param $ip string IP地址 */ public function handleLogin( $user='li.yonghuan', $pass='123456', $ip='127.0.0.1' ) { switch( rand(1,3) ) { case 1: $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); $ret = true; break; case 2: $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); $ret = false; break; case 3: $this->setStatus( self::LOGIN_USER_UNKNOWN, $user, $ip ); $ret = false; break; } $this->notify(); return $ret; } /** *设置状态值 *@param $status string 状态值 *@param $user string 用户名 *@param $ip string IP地址 */ public function setStatus( $status, $user, $ip ) { $this->loginstatus = array( $status, $user, $ip ); } /** *获取状态 *登录时产生的各种状态 */ public function getStatus() { return $this->loginstatus; } }<?php/** *接口:观察者 *@author li.yonghuan *@version 2014.01.18 * */interface Observer { /** *更新 */ function update( Observable $observable );}<?php/** *抽象类,登录观察者 *@author li.yonghuan *@version 2014.01.18 * */abstract class LoginObserver implements Observer { /** *Login 对象 *@var Login object */ private $login; /** *构造方法 *@param $login Login object */ public function __construct( Login $login ) { $this->login = $login; $login->attach( $this ); } /** *更新操作 *@param $observer Observer */ public function update( Observable $observable ) { if( $observable === $this->login ) { $this->doUpdate( $observable ); } } /** *执行更新 *@param login Login */ abstract function doUpdate( Login $login ); } <?php/** *安全监控登录,负责登录安全的观察者 *@author li.yonghuan *@version 2014.01.18 */class SecurityMonitor extends LoginObserver { /** *执行更新 *@param $login Login */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_WRONG_PASS ) { //发送邮件给系统管理员 print __CLASS__.":\tsending mail to sysadmin"; } }} <?php/** *正确登录,观察者 *@author li.yonghuan *@version 2014.01.18 */class GeneralLogger extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_ACCESS ) { //记录登录数据到日志 print __CLASS__.":\tadd login data to log"; } }} <?php/** *用户名错误,观察者 *@author li.yonghuan *@version 2014.01.18 */class UserMonitor extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_USER_UNKNOWN ) { //用户名错误 print __CLASS__.":\tusername is uncorrect"; } }} /** * 观察者模式 */ public function actionObserver(){ Yii::import('ext.observer.*'); $login = new Login(); //添加安全观察者 $login->attach(new SecurityMonitor( $login )); //添加正确登录观察者 $login->attach(new GeneralLogger( $login )); //添加用户名观察者 $login->attach(new UserMonitor( $login )); $login->handleLogin(); }<?php /** * 主题功能 */ class Observable{ /** * 添加观察者 */ function attact (Observer $observer); /** * 删除观察者 */ function detach (Observer $observer); /** * 通知观察者 */ function notify (); } <?php /** * 主体类 * 被观察者 */ class Login implements Observable{ /** *密码错误状态 */ const LOGIN_ACCESS = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_USER_UNKNOWN = 3; /** *登录时的状态 * */ private $loginstatus; /** *观察者列表 *@var array */ private $observers; /** *构造方法 * */ public function __construct(){ $this->observers = array(); } /** *添加观察者 *@param $observer Observer object */ public function attach( Observer $observer ){ $this->observers[] = $observer; } /** *删除观察者 *@param $observer Observer object */ public function detach( Observer $observer ){ $newobservers = array(); foreach( $this->observers as $obs ){ if( $obs != $observer ){ $newobservers[] = $observer; } } $this->observers = $newobservers; } /** *通知观察者 * */ public function notify(){ foreach( $this->observers as $obs ){ $obs->update( $this ); } } /** *处理登录 *@param $user string 用户名 *@param $pass string 密码 *@param $ip string IP地址 */ public function handleLogin( $user='li.yonghuan', $pass='123456', $ip='127.0.0.1' ) { switch( rand(1,3) ) { case 1: $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); $ret = true; break; case 2: $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); $ret = false; break; case 3: $this->setStatus( self::LOGIN_USER_UNKNOWN, $user, $ip ); $ret = false; break; } $this->notify(); return $ret; } /** *设置状态值 *@param $status string 状态值 *@param $user string 用户名 *@param $ip string IP地址 */ public function setStatus( $status, $user, $ip ) { $this->loginstatus = array( $status, $user, $ip ); } /** *获取状态 *登录时产生的各种状态 */ public function getStatus() { return $this->loginstatus; } } <?php /** *接口:观察者 *@author li.yonghuan *@version 2014.01.18 * */ interface Observer { /** *更新 */ function update( Observable $observable ); } <?php /** *抽象类,登录观察者 *@author li.yonghuan *@version 2014.01.18 * */ abstract class LoginObserver implements Observer { /** *Login 对象 *@var Login object */ private $login; /** *构造方法 *@param $login Login object */ public function __construct( Login $login ) { $this->login = $login; $login->attach( $this ); } /** *更新操作 *@param $observer Observer */ public function update( Observable $observable ) { if( $observable === $this->login ) { $this->doUpdate( $observable ); } } /** *执行更新 *@param login Login */ abstract function doUpdate( Login $login ); } <?php /** *安全监控登录,负责登录安全的观察者 *@author li.yonghuan *@version 2014.01.18 */ class SecurityMonitor extends LoginObserver { /** *执行更新 *@param $login Login */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_WRONG_PASS ) { //发送邮件给系统管理员 print __CLASS__.":\tsending mail to sysadmin"; } } } <?php /** *正确登录,观察者 *@author li.yonghuan *@version 2014.01.18 */ class GeneralLogger extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_ACCESS ) { //记录登录数据到日志 print __CLASS__.":\tadd login data to log"; } } } <?php /** *用户名错误,观察者 *@author li.yonghuan *@version 2014.01.18 */ class UserMonitor extends LoginObserver { /** *观察者更新 * */ public function doUpdate( Login $login ) { $status = $login->getStatus(); if( $status[0] == Login::LOGIN_USER_UNKNOWN ) { //用户名错误 print __CLASS__.":\tusername is uncorrect"; } } } /** * 观察者模式 */ public function actionObserver(){ Yii::import('ext.observer.*'); $login = new Login(); //添加安全观察者 $login->attach(new SecurityMonitor( $login )); //添加正确登录观察者 $login->attach(new GeneralLogger( $login )); //添加用户名观察者 $login->attach(new UserMonitor( $login )); $login->handleLogin(); }画布 14模版模式<?php/** *模版模式基类 */abstract class Template{ public function templateA(){} public function templateB(){} public function getTemplate(){ $this->templateA(); $this->templateB(); }}<?php/** * 子类 */class TemplateChild extends Template{ public function templateA(){ echo 'A'; } public function templateB(){ echo 'B'; }} /** *模版方法 */ public function actionTemplate(){ Yii::import('ext.template.*'); $templateC = new TemplateChild; $templateC->getTemplate(); } <?php /** *模版模式基类 */ abstract class Template{ public function templateA(){} public function templateB(){} public function getTemplate(){ $this->templateA(); $this->templateB(); } } <?php /** * 子类 */ class TemplateChild extends Template{ public function templateA(){ echo 'A'; } public function templateB(){ echo 'B'; } } /** *模版方法 */ public function actionTemplate(){ Yii::import('ext.template.*'); $templateC = new TemplateChild; $templateC->getTemplate(); }画布 15职责链模式<?php/** *职责链抽象类 */abstract class Chain{ public $chain; public function setChain($chain){ $this->chain = $chain; } public function handleRequest($request){}}<?php/** *职责链一号 *计算值是否为0 */class ChainZero extends Chain{ public function handleRequest($num){ if($num == 0){ echo '此数为0 职责链停止<br/>'; }else{ echo 'zero<br/>'; $this->chain->handleRequest($num); } }}<?php/** *职责链一号 *计算值是否为奇数 */class ChainEven extends Chain{ public function handleRequest($num){ if($num%2 == 1){ echo '此数为奇数 职责链停止<br/>'; }else{ echo 'even<br/>'; $this->chain->handleRequest($num); } }}<?php/** *职责链一号 *计算值是否为偶数 */class ChainOdd extends Chain{ public function handleRequest($num){ if($num%2 != 1){ echo '此数为偶数 职责链停止<br/>'; }else{ echo 'odd<br/>'; $this->chain->handleRequest($num); } }} /** *职责链模式 */ public function actionChain(){ Yii::import('ext.chain.*'); $chainZero = new ChainZero(); $chainEven = new ChainEven(); $chainOdd = new ChainOdd(); $chainZero->setChain($chainEven); $chainEven->setChain($chainOdd); foreach(array(2,3,4,5,0) as $num) { $chainZero->handleRequest($num); } }<?php /** *职责链抽象类 */ abstract class Chain{ public $chain; public function setChain($chain){ $this->chain = $chain; } public function handleRequest($request){} } <?php /** *职责链一号 *计算值是否为0 */ class ChainZero extends Chain{ public function handleRequest($num){ if($num == 0){ echo '此数为0 职责链停止<br/>'; }else{ echo 'zero<br/>'; $this->chain->handleRequest($num); } } } <?php /** *职责链一号 *计算值是否为奇数 */ class ChainEven extends Chain{ public function handleRequest($num){ if($num%2 == 1){ echo '此数为奇数 职责链停止<br/>'; }else{ echo 'even<br/>'; $this->chain->handleRequest($num); } } } <?php /** *职责链一号 *计算值是否为偶数 */ class ChainOdd extends Chain{ public function handleRequest($num){ if($num%2 != 1){ echo '此数为偶数 职责链停止<br/>'; }else{ echo 'odd<br/>'; $this->chain->handleRequest($num); } } } /** *职责链模式 */ public function actionChain(){ Yii::import('ext.chain.*'); $chainZero = new ChainZero(); $chainEven = new ChainEven(); $chainOdd = new ChainOdd(); $chainZero->setChain($chainEven); $chainEven->setChain($chainOdd); foreach(array(2,3,4,5,0) as $num) { $chainZero->handleRequest($num); } }画布 16状态模式举例来说:一个人具有生气,高兴和抓狂等状态,在这些状态下做同一个事情可能会有不同的结果,一个人的心情可能在这三种状态中循环转变。使用一个moodState类表示一个人的心情,使用mad,Happy,Angry类代表不同的心情<?php/** * 状态接口基类 */interface State{ public function handle($state); public function display();}<?php/** * 不同的环境改变不同的状态 */class Context{ private $state = null; public function __construct($state){ $this->setState($state); } public function setState($state){ $this->state = $state; } public function request(){ $this->state->display(); $this->state->handle($this); }}<?php/** * 状态类A */class StateA implements State{ public function handle($context) { $context->setState(new StateB()); } public function display() { echo "state A<br/>"; } }<?php/** * 状态类B */class StateB implements State{ public function handle($context) { $context->setState(new StateC()); } public function display() { echo "state B<br/>"; }}<?php/** * 状态类C */class StateC implements State{ public function handle($context) { $context->setState(new StateA()); } public function display() { echo "state C<br/>"; }} /** *状态模式 */ public function actionState(){ Yii::import('ext.state.*'); $objContext = new Context(new StateB()); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); }举例来说:一个人具有生气,高兴和抓狂等状态,在这些状态下做同一个事情可能会有不同的结果,一个人的心情可能在这三种状态中循环转变。使用一个moodState类表示一个人的心情,使用mad,Happy,Angry类代表不同的心情 <?php /** * 状态接口基类 */ interface State{ public function handle($state); public function display(); } <?php /** * 不同的环境改变不同的状态 */ class Context{ private $state = null; public function __construct($state){ $this->setState($state); } public function setState($state){ $this->state = $state; } public function request(){ $this->state->display(); $this->state->handle($this); } } <?php /** * 状态类A */ class StateA implements State{ public function handle($context) { $context->setState(new StateB()); } public function display() { echo "state A<br/>"; } } <?php /** * 状态类B */ class StateB implements State{ public function handle($context) { $context->setState(new StateC()); } public function display() { echo "state B<br/>"; } } <?php /** * 状态类C */ class StateC implements State{ public function handle($context) { $context->setState(new StateA()); } public function display() { echo "state C<br/>"; } } /** *状态模式 */ public function actionState(){ Yii::import('ext.state.*'); $objContext = new Context(new StateB()); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); $objContext->request(); }画布 17访问者模式<?php/** * 访问者模式 */abstract class Visitor{ abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element);}<?phpclass ConcreteVisitor1 extends Visitor{ public function visitCroncreteElementA($element) { echo get_class($element)." visit 1A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 1B<br/>"; }}<?phpclass ConcreteVisitor2 extends Visitor{ public function visitCroncreteElementA($element) { echo get_class($element)." visit 2A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 2B<br/>"; }}<?phpabstract class Element{abstract public function accept($visitor);}<?phpclass ObjectStructure{ private $_elements = array(); public function attach($element) { $this->_elements[] = $element; } public function detach($element) { if($key = array_search($element,$this->_elements) !== false) unset($this->_elements[$key]); } public function accept($visitor) { foreach($this->_elements as $element) { $element->accept($visitor);% } }} /** *访问者模式 */ public function actionVisitor(){ Yii::import('ext.visitor.*'); $objOS = new ObjectStructure(); $objOS->attach(new ConcreteElementA()); $objOS->attach(new ConcreteElementB()); $objCV1 = new ConcreteVisitor1(); $objCV2 = new ConcreteVisitor2(); $objOS->accept($objCV1); $objOS->accept($objCV2); } <?php /** * 访问者模式 */ abstract class Visitor { abstract public function visitCroncreteElementA($element); abstract public function visitCroncreteElementB($element); } <?php class ConcreteVisitor1 extends Visitor { public function visitCroncreteElementA($element) { echo get_class($element)." visit 1A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 1B<br/>"; } } <?php class ConcreteVisitor2 extends Visitor { public function visitCroncreteElementA($element) { echo get_class($element)." visit 2A<br/>"; } public function visitCroncreteElementB($element) { echo get_class($element)." visit 2B<br/>"; } } <?php abstract class Element { abstract public function accept($visitor); } <?php class ObjectStructure { private $_elements = array(); public function attach($element) { $this->_elements[] = $element; } public function detach($element) { if($key = array_search($element,$this->_elements) !== false) unset($this->_elements[$key]); } public function accept($visitor) { foreach($this->_elements as $element) { $element->accept($visitor); } } } /** *访问者模式 */ public function actionVisitor(){ Yii::import('ext.visitor.*'); $objOS = new ObjectStructure(); $objOS->attach(new ConcreteElementA()); $objOS->attach(new ConcreteElementB()); $objCV1 = new ConcreteVisitor1(); $objCV2 = new ConcreteVisitor2(); $objOS->accept($objCV1); $objOS->accept($objCV2); }画布 18中介者模式<?php/** * 中介者模式 * 中介者抽象基类 */abstract class Mediator{ public function send($message, $colleague){ }}<?php/** * 同事基类 * 用于同事之间发送信息 */abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){}}<?php/** * 具体中介者 */class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; }}<?php/** * 具体同事类 * */class ColleagueA extends Colleague{ /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; }}<?php/** * 具体同事类 * */class ColleagueB extends Colleague{ public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; }}/** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } <?php /** * 中介者模式 * 中介者抽象基类 */ abstract class Mediator{ public function send($message, $colleague){ } } <?php /** * 同事基类 * 用于同事之间发送信息 */ abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){} } <?php /** * 具体中介者 */ class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; } } <?php /** * 具体同事类 * */ class ColleagueA extends Colleague { /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; } } <?php /** * 具体同事类 * */ class ColleagueB extends Colleague { public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; } } /** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } 画布 19解释器模式代码实例:<?phpclass Expression{ function interpreter($str) { return $str; }}<?phpclass ExpressionNum extends Expression{ function interpreter($str) { switch($str) { case "0": return "零"; case "1": return "一"; case "2": return "二"; case "3": return "三"; case "4": return "四"; case "5": return "五"; case "6": return "六"; case "7": return "七"; case "8": return "八"; case "9": return "九"; } }} <?phpclass ExpressionCharater extends Expression{ function interpreter($str) { return strtoupper($str); }}<?phpclass Interpreter{ function execute($string) { $expression = null; for($i = 0;$i<strlen($string);$i++) { $temp = $string[$i]; switch(true) { case is_numeric($temp): $expression = new ExpressionNum(); break; default: $expression = new ExpressionCharater(); break; } echo $expression->interpreter($temp); } }} /** *解释器模式 */ public function actionExpression(){ Yii::import('ext.expression.*'); $obj = new Interpreter(); $obj->execute("12345abc"); } 代码实例: <?php class Expression { function interpreter($str) { return $str; } } <?php class ExpressionNum extends Expression { function interpreter($str) { switch($str) { case "0": return "零"; case "1": return "一"; case "2": return "二"; case "3": return "三"; case "4": return "四"; case "5": return "五"; case "6": return "六"; case "7": return "七"; case "8": return "八"; case "9": return "九"; } } } <?php class ExpressionCharater extends Expression { function interpreter($str) { return strtoupper($str); } } <?php class Interpreter { function execute($string) { $expression = null; for($i = 0;$i<strlen($string);$i++) { $temp = $string[$i]; switch(true) { case is_numeric($temp): $expression = new ExpressionNum(); break; default: $expression = new ExpressionCharater(); break; } echo $expression->interpreter($temp); } } } /** *解释器模式 */ public function actionExpression(){ Yii::import('ext.expression.*'); $obj = new Interpreter(); $obj->execute("12345abc"); } 画布 20代理模式<?php /** * 代理模式 * 接口类 */interface IGiveGift{ public function giveDolls(); public function giveFlowers(); public function giveChocolate();}<?php/** * 追求者 * 实现送礼物接口 */class Pursuit implements IGiveGift{ public $mm; public function __construct($mm){ $this->mm = $mm; } public function giveDolls(){ echo $this->mm .'送你娃娃'; } public function giveFlowers(){ echo $this->mm .'送你花'; } public function giveChocolate(){ echo $this->mm .'送你巧克力'; }}<?php /** * 追求者的朋友 * 真正的代理 */class Proxy implements IGiveGift{ public $pursuit; public function __construct($mm){ $this->pursuit = new Pursuit($mm); } public function giveDolls(){ $this->pursuit->giveDolls(); } public function giveFlowers(){ $this->pursuit->giveFlowers(); } public function giveChocolate(){ $this->pursuit->giveChocolate(); }} /** * 代理模式 */ public function actionProxy(){ Yii::import('ext.proxy.*'); $proxy = new Proxy('娇娇'); $proxy->giveDolls(); $proxy->giveFlowers(); $proxy->giveChocolate(); } <?php /** * 代理模式 * 接口类 */ interface IGiveGift{ public function giveDolls(); public function giveFlowers(); public function giveChocolate(); } <?php /** * 追求者 * 实现送礼物接口 */ class Pursuit implements IGiveGift{ public $mm; public function __construct($mm){ $this->mm = $mm; } public function giveDolls(){ echo $this->mm .'送你娃娃'; } public function giveFlowers(){ echo $this->mm .'送你花'; } public function giveChocolate(){ echo $this->mm .'送你巧克力'; } } <?php /** * 追求者的朋友 * 真正的代理 */ class Proxy implements IGiveGift{ public $pursuit; public function __construct($mm){ $this->pursuit = new Pursuit($mm); } public function giveDolls(){ $this->pursuit->giveDolls(); } public function giveFlowers(){ $this->pursuit->giveFlowers(); } public function giveChocolate(){ $this->pursuit->giveChocolate(); } } /** * 代理模式 */ public function actionProxy(){ Yii::import('ext.proxy.*'); $proxy = new Proxy('娇娇'); $proxy->giveDolls(); $proxy->giveFlowers(); $proxy->giveChocolate(); }画布 21享元模式<?php/** * 抽象享元角色 */abstract class Flyweight{ abstract public function operation($state);}<?php /** * 具体享元角色 */class ConcreteFlyweight extends Flyweight{ private $_intrinsicState = null; /** * @param $state 内部状态 */ public function __construct($state){ $this->_intrinsicState = $state; } public function operation($state) { echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; }}<?php/** * 不共享的具体享元,客户端直接调用 */class UnsharedConcreteFlyweight extends Flyweight { private $_intrinsicState = null; /** * 构造方法 * @param string $state 内部状态 */ public function __construct($state) { $this->_intrinsicState = $state; } public function operation($state) { echo 'UnsharedConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } }<?php /** * 享元工厂角色 */class FlyweightFactory{ private $_flyweights; public function __construct(){ $this->_flyweights = array(); } public function getFlyweight($state){ if(isset($this->_flyweights[$state])){ return $this->_flyweights[$state]; } return $this->_flyweights[$state] = new ConcreteFlyweight($state); }} /** * 享元模式 */ public function actionFlyweight(){ Yii::import('ext.flyweight.*'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state A'); $flyweightFactory->operation('other state A'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state B'); $flyweightFactory->operation('other state B'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state C'); $flyweightFactory->operation('other state C'); /* 不共享的对象,单独调用 */ $uflyweight = new UnsharedConcreteFlyweight('state A'); $uflyweight->operation('other state A'); } <?php /** * 抽象享元角色 */ abstract class Flyweight{ abstract public function operation($state); } <?php /** * 具体享元角色 */ class ConcreteFlyweight extends Flyweight{ private $_intrinsicState = null; /** * @param $state 内部状态 */ public function __construct($state){ $this->_intrinsicState = $state; } public function operation($state) { echo 'ConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } } <?php /** * 不共享的具体享元,客户端直接调用 */ class UnsharedConcreteFlyweight extends Flyweight { private $_intrinsicState = null; /** * 构造方法 * @param string $state 内部状态 */ public function __construct($state) { $this->_intrinsicState = $state; } public function operation($state) { echo 'UnsharedConcreteFlyweight operation, Intrinsic State = ' . $this->_intrinsicState . ' Extrinsic State = ' . $state . '<br />'; } } <?php /** * 享元工厂角色 */ class FlyweightFactory{ private $_flyweights; public function __construct(){ $this->_flyweights = array(); } public function getFlyweight($state){ if(isset($this->_flyweights[$state])){ return $this->_flyweights[$state]; } return $this->_flyweights[$state] = new ConcreteFlyweight($state); } } /** * 享元模式 */ public function actionFlyweight(){ Yii::import('ext.flyweight.*'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state A'); $flyweightFactory->operation('other state A'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state B'); $flyweightFactory->operation('other state B'); $flyweightFactory = new FlyweightFactory(); $flyweightFactory->getFlyweight('state C'); $flyweightFactory->operation('other state C'); /* 不共享的对象,单独调用 */ $uflyweight = new UnsharedConcreteFlyweight('state A'); $uflyweight->operation('other state A'); }画布 22策略模式<?php/** * 策略模式接口 * */interface FlyBehavior{ public function fly();}<?php/** *用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */class FlyWithWings implements FlyBehavior{ /** *飞行方法 * */ public function fly(){ echo 'fly with wings'; }}<?php/** *不用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */class FlyWithNo implements FlyBehavior{ /** *飞行方法 */ public function fly(){ echo 'fly with no'; }}<?php/** *鸭子类 *@author li.yonghuan *@version 2014.01.17 */class Duck{ /** *飞行实例 *@var FlyBehavior object */ private $_flyBehavior; /** *开始飞 * */ public function performFly(){ $this->_flyBehavior->fly(); } /** *设置飞行实例 *@param $behavior Flybehavior */ public function setFlyBehavior( FlyBehavior $behavior ){ $this->_flyBehavior = $behavior; }}<?php/** *橡皮鸭 *@author li.yonghuan *@version 2014.01.17 */ class RubberDuck extends Duck{ } /** * 策略模式 */ public function actionStrategy(){ Yii::import('ext.strategy.*'); $duck = new RubberDuck(); /* 橡皮鸭用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 橡皮鸭不用翅膀飞行 */ $duck->setFlyBehavior( new FlyWithNo() ); $duck->performFly(); }<?php /** * 策略模式接口 * */ interface FlyBehavior{ public function fly(); } <?php /** *用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */ class FlyWithWings implements FlyBehavior{ /** *飞行方法 * */ public function fly(){ echo 'fly with wings'; } } <?php /** *不用翅膀飞行 *@author li.yonghuan *@version 2014.01.17 */ class FlyWithNo implements FlyBehavior{ /** *飞行方法 */ public function fly(){ echo 'fly with no'; } } <?php /** *鸭子类 *@author li.yonghuan *@version 2014.01.17 */ class Duck{ /** *飞行实例 *@var FlyBehavior object */ private $_flyBehavior; /** *开始飞 * */ public function performFly(){ $this->_flyBehavior->fly(); } /** *设置飞行实例 *@param $behavior Flybehavior */ public function setFlyBehavior( FlyBehavior $behavior ){ $this->_flyBehavior = $behavior; } } <?php /** *橡皮鸭 *@author li.yonghuan *@version 2014.01.17 */ class RubberDuck extends Duck{ } /** * 策略模式 */ public function actionStrategy(){ Yii::import('ext.strategy.*'); $duck = new RubberDuck(); /* 橡皮鸭用翅膀飞行 */ $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); /* 橡皮鸭不用翅膀飞行 */ $duck->setFlyBehavior( new FlyWithNo() ); $duck->performFly(); }画布 23备忘录模式代码实例:<?php/** * 发起人角色 */class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); }<6,xhtml:p> public function show(){ echo "<br/>State=".$this->state; }}<?php/** * 备忘录角色 */class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; }}<?php/** * 管理角色 */class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; }} /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); }代码实例: <?php /** * 发起人角色 */ class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); } public function show(){ echo "<br/>State=".$this->state; } } <?php /** * 备忘录角色 */ class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; } } <?php /** * 管理角色 */ class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; } } /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); } 画布 24迭代器模式代码实例: 公交买票<?php /** * 迭代器抽象类 */abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem();}?><?php /** * 具体迭代器类 */class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; }}<?php /** * 聚集抽象类 */abstract class Aggregate{ abstract public function createIterator();}<?php /** * 具体聚集类 */class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } }?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }代码实例: 公交买票 <?php /** * 迭代器抽象类 */ abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem(); } ?> <?php /** * 具体迭代器类 */ class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; } } <?php /** * 聚集抽象类 */ abstract class Aggregate{ abstract public function createIterator(); } <?php /** * 具体聚集类 */ class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } } ?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }画布 25PKWWz'PK憃H styles.xmlAPKl\FAPK憃H2Revisions/1gcdblglfb7hr323jqe93argh5/revisions.xml#{PK ##PK憃H2Revisions/7fc90t5a1lv7icmaqanh6aq576/revisions.xmlaPKOg@PK憃H2Revisions/2cq1nlpo7belihvtcunm2mi3od/revisions.xmlSPK:HYPK憃H2Revisions/5qqfvg6ug87f5h13rcttmbcmnu/revisions.xml3PK'83PK憃H2Revisions/7gfbag04ob6e3m7bku43f91p80/revisions.xml3PKZ}83PK憃H2Revisions/40an2vqcj6l3600heu3ci8os60/revisions.xml3PK1tq83PK憃H2Revisions/2s7dph2rstg9duopvd4c9fqoai/revisions.xml3PK 83PK憃H2Revisions/2mi7i0vpg09r24eaj8cf91074m/revisions.xml3PK83PK憃H2Revisions/6fb8tai7kv5annr1abck0u7h41/revisions.xml3PK+O83PK憃H2Revisions/6ao611p7omgh4jbbh1a8sr3q52/revisions.xmlSPK3ɱPK憃H2Revisions/13lrno0ou22pncrqu6nv5pivj6/revisions.xmlSPK2?رPK憃H2Revisions/2995ek6mp8msac9q0ecb6fmco8/revisions.xmlSPK+wPK憃H2Revisions/2rtivbko6n511kg6sb321ure3v/revisions.xmlSPKXPK憃H2Revisions/4p6uej7l6jjegt16dmlnog6k54/revisions.xml3PK#F83PK憃H2Revisions/5f92jfntdkgpci17p5vahisq62/revisions.xmlSPK.4ӱPK憃H2Revisions/248hpb156vqrs6774uvdo5jb5o/revisions.xmlSPK2NPK憃H2Revisions/38nm1l3qtlgtrc635n4g0qpr43/revisions.xmlSPK|5PK憃H2Revisions/30eurbd38q472f822ct633nmfk/revisions.xml3PK~b83PK憃H2Revisions/0h7q7e2h31b49njdlvs6sd6v4s/revisions.xmlSPK;PK憃H2Revisions/74ie3v3u6v98jtpo8uvgo5g3kq/revisions.xmlSPK-~ױPK憃H2Revisions/2tkurlg1ui4gd8ul3ctt9pev11/revisions.xmlSPKRPK憃H2Revisions/1kns109k9tost4v4kugc5k3juf/revisions.xmlSPKlsPK憃H2Revisions/6bgih0907h24duib21oassv3vm/revisions.xmlSPK}PK憃H2Revisions/0iiumssmg62im9p55ggfrbk4b4/revisions.xml3PK83PK憃H2Revisions/14rdlng7ecgfhsvlcr94rhvpmr/revisions.xml3PK%np683PKzH*attachments/27ojvr43j99j2hvc2j2bvqign6.jpg nJFIF``C     C   " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?G+-R:eƠZ]%xc@Cy͖]Jm-"Ꮟ^$Um#)&Y1x)26ʮ7ǭBӯ5{+ְZE]`#+#6e,F]<7k:֑z~yywA̰B2$FHDWSݧ4T[zr])2iFNONU87em^Beu6uy$R #qi)x̶_iwj#f,2p FpHc+{DOEi#MckZq#J8 <3&{}j=M׬@3o/af1 3G!4e`- LhUVD.YF?8Y8> E|9_~w~.cφ|7jJԒ\,#2nԕH_̍V}˰DC,?f{7MG<?-~EmtҤ2,ٝRIչBrٷcJ}ߌy^ыR0WZw7}E|!Rx^4xiif}GIKKj6{tOW+Ox>&DŽa⛏xu|>Zé-{aȉirw3MΉCZ4_gN[4̾K%_92& AY ɿ|_}qE~fA>:S^x'׈|?ͩxnmaKc+\H:$2UzG/N/|1_⯀qAif;*;$ =sߟ}asF?z+?[rƑ|[iZbDԬΌ1@"`n3~QCo[BiZjվcz-WwfwS+:)g1uChPDϧ,\K Ytl6O9+,M3k5}E|u=m=-{95K]?kHЍ Ƨ˓vȦ Srv+mK)xngNM.C042j}hij̥y1ŶJst/^Jv_译15|Q|tw^ ]7FsۅkH"8ZR!'>xƩW<@EAnm|EKB)eInLlە?J/&[F6OkAE|ᧃ++`wdITRG)Y6Uh9{KdcFѾ#Z|a-E<)>Q*2/c*^hEP(._c5?n&$ /~23'TTdcңwU>{~_-+K?_X^ҭþL5OveApC/%u>dR!aE[)jVqxI7xizuY.uThl1H-mۇ2P{ZVkBOߋW]}yE~Cxⷉz=Jķ>UxLֆ`z2DFT+<⯉ |QeRo\}mXpYْE A2om4{QPPQEQEQEQEQEQEQEQEQEYEiZamiKdG`4:@&|[m5H/a}FjFN.DIB@b6)Ÿ8w^篮z-nIwj˩Fi SEO)X_Ʌ#V||h^,vWz5js]FV8n%Y+*RAݶ"E%_roJw{]=}o/~z??x{Nә̏u-$2)@&/py^G5#?k[~͗:ECUͫ2X~UEW;$$Eܬ?{?h0.[6{y]ɷ9~V/_x ^{ȼ3<7( }A|!ޔf־\h~BG/tX@PZFnfYmmj@ͼ!G+ w׍Kk? l|_ˍymY-)HqđBvkoN2[ߊ5/W|\shZd57ڍKu ˈH)v!?:ΟmFXҭ gEK+-[[nw`WKж,-K፶tn{]jt[gڹHd];9QcIΩGs议؝q-{dx:!fRNAכOD]xP$,K.q%q-{[O `gvel-^h6?j4 u}vf |nge~ֿP ?AJѮ4Shon퉶=X=xt:5CNҵC\X]@88?(Ӷ?xM|At_Ya>eiz$|K4h/'6*Ԛi_}ʓrտͳ̵zm[]A+RaZ[h 6Ɍ =5Uz0lu͍JM,̃۹j֢y&o=o|okzƳojI_:Ҳ7E8*| >Mg:ھz>k0XXH"LI $pS̿ӫmUok> tJ=R Tim>p&. @%ʟ%b^auh^1 occ k[[9KH{}Ng`+ $20.~qvgϚ81'i&̗Z%ȼ0}JG$P!OAz4+#OƚCͥʳ[f]]LkY58wzy_H]9zkxOh~!tmI4*ZzfK]w6l*{Id# \|?k_[ҭ/R%,!p|#b-'OQK}W /C/i35;\YxMKxn-&+m*vQ &I/'H&f!HI%wG5.UKX;4g.Ѩb\y8ٶ51W]ww1xz߇|S{]/w[1j|$P"Ҹ.ĚWMKQ^|6F7oxmcc[5VT̡$P,ŇSmw*o?ϕ%@ut7RAS[^7_ K_ZxO4v{kM7Z ٠GHy db%XGdqk~:~ߌ3[<`ʲO4 d{~Z>o]Wg8-U:|x9ְ΋wmekokkcmWn9$2to5 jW7O8/x.R  |U]'㯊|9Cuq=E4a2Y$)$qvQ=k7R3O4Ѽy$6q&Hb\طs-6M?E\Q φ~i:m m}<9o] `3NQ'v6s\߃<-o 4?9V9t˛ X;Co :Ssu<8MZ8gJ]]=KIduXJeP%_=c; `(9c?xFWp];xfhê]a+,n`C&)$t$rZ΅ƾ4~^3kkЇxKvہ&'"aU+Vo1g]WFuf$8g1/n0uڿTM)!X"Siڑ,@!i fi?:- bfL`PV$B(%2GIGk SzΙk?o $/d'AϷT2ĄNCCǍct74,B(lC>zgBVoW1z"xKD [1Nzgv_s<> ƚw"^uyo&w<d *(rL4uS]mkk#GmKǨBn_xqgV1qxp~m5ބ}k.T]- |c?jRXu)-YPlسGsv2^_]x *Sh1|߼~PeQ:*/OojQ@Š((((((((((((4xM$`As^#SzxHA$ csͲ@T) ?SM7@ߚo?▝/O!҆mwd LfXȏ`/IE0OM(syK&^hz.gU{o0d t{Sg5f#?ĚIMOxWa"P&mf80OM(?zo@Ϗdkxv>1M+Ru[7IL0\ib1LdY~J$>qkO`}Q $"=59dŸE =7/ǿ~  EVŚ%V6Pi𴹠4fLњZ)3Fhh4fLњZ)3Fhh4fOּi = |_ ōDƝe*2ڀ=[$;/ ]kj_V}=BuںP($Xe񧀵MK/xgQդ4"(b{i`V1 y8,`U>y0OM(u8s8_j,lmo*J8in|%H ԌIbtvP_xBkA$IoἩKGf.N $"S?'fZisx:^뱤q(o o|#+cMtG 'R^h)3xq/%VmޣT%׾@9T5FW2x@NFzu|_ X.51yⵅGٚYeXL}YzRWECi!_5mIYJVVSsee*y <@Ex?h |0FT}j?@^%NhgQ|3ӆ|cgΟ_ua5%WOY્ xӍ +'̓xHOo/(_?}բW1O&U+]?|@kY<T>t€foPR  W(ɿ@JG(_?}h&U+]?|@kY<T>t€foPR  W(ɿ@JG(_?}h&U+]?|@kY<;Je'#WSk.<Ν`~w\:;W?|D~!|^'Se+d+ɧUF;g9uxax־*:F0?*~ѠuFTԁ##/~ѹo~OOj?X*{>=ؚ[mEʴ*4&T5}Exv_{ 'Z` 5=;_ ?QU{m78=R}snm"gtKҵ]3MҵU9$~#9^m1v|&a;t>fGk?/"sUܭszH9RA{ Suߍ$P:q  zc=iHQK+$D?^_I>8=VWv%n|p{//KXzޅg#_iZ.qqxgTh,OB&Prd(܁"V2=8QEQEQEQEQEQEQEQEQEp|/$_;B/+?^3s_e[Ǻ_R&|q{yGE{XXui'_|oz_zU kWpA Z{q0D2;$@ <|ZK/ k+^%ͭNUWG`++*}Is=|oڽY# W-c⛟Cj6]pB8U<0ծ3qB /(QEQEQEQEQEQEQEQEQEQEQEQEQEQEWtכ~˗gKt;Y$Esܚ+[xI,omjZY=0^aEuRREPEPEPEPEPEPEPEPEPEPEPEPEPkƗ>bI+곮YN.]X|^iq|U;/<_ -_w}gC,beVq[:av.kg![ӡHA*0ZCiA1)JixOQ?![G)`F4 <_vxTozqch/#AI p$m^w; <Kw nNAgowmL"P;I(rG2}y7Y+FtPKdDC^\*c9>fORo75gx/@L~ ;ȹf;[vv)ͣw!`zz{A/~&74[goYC}VrIs_B[©@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQE|ǽq |?4nkŻKsRbژؗ72NSC],q-E{2EզN-meI; Fӈvj}>ȧSW<Ө(((((((((>g ~@FkZ&44 wcq [IVmF'IqA7G/vr5cD+ ?B}zhyG.? {om@]WNÜ̙~O!^>ڲ|,)KOji6>|nNkYFs$9"=:S`\PO~jS`b.Z8ϯls]qV~ t KDMߛu(BJZu5:4((((((((();Rv&F/^(zw=fKc?}^zuQ@Q@Q@Q@Q@Q@Q@Q@y?o+7b_?{@i-QEQEQEQEQEQEQEPt>"Qn.i'@<[iޓk<+:~мCuEڶFVh.O^:)<^'~_ nA??-п5T\3&>z t[kOƏKt/ i! t:(c'?u_*? ZG5:(c'?ο ?? O7@% k7~+itkEq{iY]B61x& [pF(1@'pޔFAO]uHO1͐ep%Re\|̲TzDL0@QH)h(7 f^]ލ|%C159Ҋ(ci^4>w1181@#W_$S"O ˞YdzY@$O$M @ kPz>(;gF{_&~#|P,!*{\͇>'=|er=w{^`?ɯ>j_| ? KwV u\\(vK'AdSdz2=Ey8C\M',9A=@(##^;'?k %xG%(,@ {p( (3@`{>%x n4 .VH$pB2=CcEW 8oZ}񃏥zG#W?;gF{_2}?'hr=E|H@#AOk>#Q#?XKiZ35ψuZ87sx.YOn{AZ\Q^M!A88=G,Š*{N?JQFG'(?žXdzYk {OX y}A0|p;?W#pqג|. 7ƵcEWioi>(5cY{[{v'k( GMɞ: 7.ONz?em8;N;g$qF8,?:eZRM0 Bf[YXeFMݔ[3⯆u{[;-9,In"4d ;p>U [f;N @uw z'i}SWSrʈ.S NT`6F'ΝH ռȢXmcy>ӼJQErNJyRdP 9{z-~ h7VrG|ȗjav(FLا+Uխ綻#{q=e.Yپh2  u"{f|d5-{Zn'c>B`U }`[ڝ)KY嵕 #"KUY6Et5䟴s46W]o&Ia,#Vf*84Ҽ@ό)|v4KWx#;}"EP_/>:վx⏋tK?j?dE#B݂±= wYliV}߂eDIկn) @a49m}Ę.<6xWS6B[ho-$Pl^hԍ@SsU|_hƉz4ïi]Ͷ($_()lS?G[}Y>KsNJ ##5wÞ H_ X-.69mؾ&iZ;3Wu}Omki Vغ3;\Dk9]IM)a֓g|κ] 8dG;3USpGi ҷ0s.s\_sV xoxoD~$[r#fb;*>q#gdپ1]νđu-G)?e* D >Ծ%ͧjɡkWߛh,0jƎUySI53%7f?k-&-l eĀ:MvKž-N/,'X|J>i>tT['yG2CP rs^Xɭ|e7Y#W~|`lu/G^YCq{y7w8I;+qEZB v7OB c<3/^ Azz[1y7φ9dȲ8PQj~~unYfl+;ɠ94o Xj ^xGKsg˖"Evf7lx>3x-׌5k?jX?o<ᢍ'Y؀Hbm؆/URZXeyQv!$wdV!cWi_tFF9akwq}uoO3BwbI'hȼRxïC95 J-`ZY>tpcT!A7ןgF|?i'@ƕyܮܵN6K+7EHK; wKm ú"WFLVM (dXg )~kWx:S>EDFEpQ+…@SO{L| MFѵIѼEn/쵽Ȝk x}n5_XfɮZ]jBjZO-C!#|J|:/mjv_E+߹iےz9@O!|K/_x?kzҥ)q:pP[ |9wbrHlws|<}SS77Xx$I!i:̨J;3* >7φ>o뭦j_M;hFu1`]ƽ)Rn |Cy7xmdN*P;/.kk询F(1{F0-.όMҹ_z_p}x_O0|do-M{iD$iFk#(QEQEQEQEy,5?Qg?Ʒ~|?–ZD^j֚T:^cF! g8~`a;Mu ހ)&Lt>[{wK#FY@ `q8r{_E{-rSm>Ծ\߷ W&|'qP.K?$ D@ǜ o iwK{;Ϸ)c&f 4r2m+Tл|0MĒKguu W$Y&(8kK-qtBo 4;JEB7 W~O%j)3\2"=aѦr2Dž=dCC,G䑤; VuP^M{Jolť׬ד|ƛ?1it KHQEWx|R]C #j|7Jb6? [lڣR2hٷ&8[?^t6%['z: CCͿ 3 ?5G3o_% zWiwGͿ 3 ?5G3o_% zWZof߄K|/=gƫh6mKDOY?~-gj&of߄K|/=gƫhi /5 ;῅,Bтʀ_IN:s?jg TC( (< `x;Y z_ٿ3wIc[֙~ޱNc<=nE`a,i%_ܟ w|?=KPl ψ5e'/.<7#,rC" Ok#`%f4{UO*0IA-Ch$ۖڙkO[eӼi ɹ#[7=:܊), mo9}rSps}*_c?.jP_^gnvA5J4'3> 1@G?1j_]M|f.L_`Wo~Lm=k@@1CB!sP‡Rњ/c?.jP_G15(u/HmhC>xTt;o-4u U/]9>Vuāq\A^P(_ڼ/d!z_ >*<4n~Ǫ]Q_y-%yj=^X`~˿Ou3]~~-ũo3SKUd'#9|>~t_KcK<1aij_ ʟsnVW9]kxׁkm~|' ^M?,f!4YƳpO&6{s̓]j;c >WjwJ#Z( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ("`vϭx֏ƾ&}bO/U,u[)/%3=Զ6c=^ڼmĿ9xOw7!4|OkD|Ok׫'ޝ@O =G,o?GMz(?S4D|Ok׬Q@;O}a-RhI4. .}#>O4PD|Ok =^Ey?,o?GM(?S5Px6_xv>'H{VsŒnXB=z<8'9xe-|b/{i]Ѷ\Y\-牰@e#!epO{ڼ~$qxIHjR+!/ RIɴdmі,@})QE|U [XZ G< ()$ITOTU@Q =G,o?GMz(?S4D|Ok׬Q@O =QODk('Gž>9gw/֥߂vZڣ_s,Aja>7<|O[O`nLP$K*'GGSH&W@w)GC_6!Ƨa<%׭<wŘIh׾xGo|;g7iRQe!:Xd`X2@4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE'joٴAJ3&^(w= kf_ֆ5;Vlb=OQxVTPѪ82O?:?>*OE֗k[>o3[`04 #GXovoÿx?Isu|C6>kl>%P(J@`30_4n_񕭴^7մ+^|ka`V >J33g5.ņРŘj~5fCZť% )%<ʴQ* cMB=:0#=ޠX~uO>0UtW<1s6l?`Q xỲB|uFK#yˍcĺ}Ƈ%PIzS|lV;\C#p4aT5g^>*|Idދul4/ohUvr|_A7~;]v\]&)mm܆B0\ D, RHSHg%4$*X!azG+oq#Xғķ}~6vnU6x0Ĵ9Q|F¸)4jz\^$;jQxWFX@ wBdJ"}W|}5Wvy3*ysHdUۀ4zC Ğ% =v;UM(nb#={מ]iO}wS1eᆵ{{a01YJ䍆 oڗH_o-a #c#>%5;(ڣH7JVV8)?x*>+j#4=^JR78I飐 fIt 0m g$q_~ xE[t[d-^x&nh$GQ[(F1\b*&sxfN]xn%[tt2= N ej0=H$#|sF^e ާZZ,w}/Ἲ.-$كS~$:SGNJm}vI:b$Iݸ {e ހv܍;ƚ?FPikimxVuPF YF#z޿ AkN// imMh\\YBmeyvc%xPեx,=y4֞4"iHBܰp;#={?gox5oiDV>|o ;YU\wm>Iqw?xcCVT0bY#21 Au_^ PS־}ϋZkp55:̉mpRU9X)Bm//kWzho?MV ZwY ),w }U/ 3EHw =OZe Wߊn}#~4 :gC b87ۆN8AҨ|;<[GRYXtx#9'J"`)1튱EUH ~Q<~9/:f}YZXKyw^qq{ayΎ=4Voѳ︟3NNQW#wzNE럚Q@Q@Q@Q@Q@Q@Q@Q@ xswû=sM5k;V--ռޡqt=²H ״Q@ru9#Um|Z/X]_%; UQkawʪz(?-З,.UGů*8B_U_KwGd+}*Ŭ_vUz=_Kwk ~UPm|Z/X]_%; UW@qkawʪ?-З,.U^Eyů*B_Uz=_Kwk ~UPm|Z/X]_%; UW@qkawʪ|-[Fi^;@4K֧Yn.leV! Z?1rH(((((PKI,pn nPKzH*attachments/2o3aksuum2j6kim7cj7mlfhmbe.jpgG<JFIF``C     C   0m" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Eп a^"k$Γ L%C*I29#Ex vZph֛ 쓹u dpXȅY7W&&F. yE|IO*8CNmit:$*cLnOc>Vinrua3ú}g_ vH`ú|i>gwtU}Sqi G*?F8gr7"ꏠ-}S搷[E,jȊ6ԞIWbzc͡:nKmeK phҦyŽ[ו'MJkxcZo. Vro[}bu*E4#;eanyi f ka ~%j+[߲{/k<;ZٖI8qTk-'A^x{u\O[zN#w1zPx@iӖ&b$kGٮ,^ۧRM[9F+GK]w=FˡkP𮟭~;l4[YlnmAp.on9Q`@2TB='&o.ojՕ1γiRY[_˰71m1(X#;`ŬUw677oEiݗr֮ќgJ-Z-ediqjZ&giҖX\$BAz֕peM.h܅<@ shx gl\h;g>^&*.i|V4*ׄojr[iQEQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@t/X׼t b$4bʗ1,IVB@ f_КM @*K)AEٜk]|?4~vVݹ9Zx#ÞѴ 3IU[(`(vU힕EJW:eJ2Ijݛv6úMc\w_Kn=q0nKH&9%0vqSWdbM6V^K]=5{(OR^}}]4+G!#Q>|j<#xLM7]tgOFW[MB9 pF@'^4FXIN2iޞ]7LѴ{ > +h(-U(3 (B({~9~x^-A \M$̐F3I"(ua\O4^B"/3IN-_}X(P^hP^k(P^hP^k(P^hP^kjO x{IuoxL`{j) (Go'U^^SXɬe7Yը((((((((((( KAz_xW(QEQEQEQEQEy?9$Ə ƽb[kcGc^@Q@Q@Q@SXɬe7Yիk5&?C5zQEQEQEQEQEQEQEQEQEQEQEQп a^"U @*[Q@5iկt[⿂tNVvpHdtiVA c;/?㴟g${W)ET?~e6?vZkY|Mw_Sckը)ET?~e6?vZ F_U4i)t[Yxـ`I#WA^OOG:'4' &Ԯ6Y,m,[s "I d0 zT|@/^Ey?*[E]#hQwK-z󗂼;3~:\Kjuv-t>Wk HZOW7oOEzy?*[E]#hQwK-z.|Y k~>3FlӯIңi-卣C \*dr+袀 ( ( ( ( ( ( ( ( ( ( ((_xW KAz-(g~͟#?^lğ9OwQEQEQEwcIXCZ_o֭,=Ԃ).K݁!NUI+HQEQEy7+7νf?g^@Q@Q@2 j>!n^J͸8$,q;HTI ?#@o / ß[ OU嶆IGt"DQ dO׸PKG?q/A_? z?7xh_^EyO4 7"?#@o ׫Q@E}Rx#LӼuiioK5BĊ ff68I'+l/`Ԭm[\F"da8bVï'eZh(((((E^:,??U (# e={gR]WC?Krѳ%ګm2(C'':b쿎2|>~C'':b쿎2|>~C'':b쿎2|>~C'':b'Ddмa'u{X)KkeEgmcbo>G^kgrI'2ƠabPyE޳Pq6;_"^ 7|)>OZ[E59PK m#"P8jo '_*b ( ( (8?E> ؿ4I?k>8bVï'eZh(((((E^:,??U (Q@Q@Q@Q@Q@yAxUWٰ4.i!@kpTyrNxÿ~$A5|K>xMO.n-Hݢ#fV yP s]>Ur 41>*3]pvll`LTo4>;W~GOۛwRLգtKk]$ۭ"M+Ƞ E{p7 %䩩kbɵh@2Y? ( cIb9g-oDRogo H$(pt .$_S/*Rx#GŷmFMW-ëHNo䪔RY4֯6Ws wSt^4oBs"2gQ*H~&i.R|cψʍNA?z8]-ŵI|;ʪúŸ|,5[Msݖ{æA>o:$leW%% w!OB|[4V[Emv%x4he[,;cFP$/_ i_XԠǞkK,Ɣ2z?牾xCX$_EĊC9d">?SW"_:3v| bNPSv uu 5¨E_%?bU?xG" HZ(T|@/G*[E]#k('QwK-> n tEXu*"#!"kDҢдk 6w;ti,U('@Q@Q@Q@Q@Q@Q@t/X׼GB%{>#rڕ-lԮ-XA>OA@Ǥ^//3( ?{{h?{{h( ?{{h?{{h( ?{{h?{{h( ?{{h?{{h( ?{{h?{{hsm`[o J|M3O&Ӯ-mG؆Gw78#'zWͿusC]KejwL)D^cops^ kZگ#P?|> | 7a$]٘$&/QEQEQEGB%{|!'B%{|!'Kc _=e=ߛNdCUVs P9n[[Oh;ZRIլ-/{xYQ|@i|`ŧF|c\X,$I$WyhAe ƾ[/s]u]ON:ׇ-BX 1AB{AP ;0g>E=ƛow4q< #.HR8Gᾯe[)[e<7 w*'I4{+na=&^MO\K/BnO@%M / T5|?5x <6ڰVonl|@ J {Z)\yx2z%ՎG Ŕ#*-/X_M{NJ~>=N:牭u+ A=E+K~j2.2IL+±ǟ/6v:Yr̷/=4xJЧS't!YQrJ@0c|ssks9,I%AI(<[M|wZהfq H]JA"(bPZG8'jqxy-GwSbs׉жhAjC0a A3\?̇Dvuzi [B8j@̟Uo-0{ !KFHA$OE xsصm>şng Txo|0r//&we>⺪'煛]K wHd5̑GA@\ϋ>;nx^<n)&7!R tPh>ϊ|:ݶjvB3*FɎ'|^qnPM#W]s^,egKf\hD{}ԃ@-σ Ʋcx{m>-Jxm;(YcJjr9_刮0Fj~Ӛ3Ei|]VJGkWo}(2\%M7=jYAxƹӎF~֤Dc[֕T\;/5έ54K 3zq@Q@Q@Q@5j'^"g_^-^i(Q@Q@Q@t/X׼7Bz/X׼7Bz9(W Utx_úWu`|3u'f!-n;@$(-#QAf<MqK7<.#Ft&1wJ6gDp lt>{Jt};OA,qFU>r ( ( qG݃Ϸcq2_"/j''W?b`d'>X'h(((Y'--Y'--(?c+c`jW?c+c`jQEQEQEP״ Wx@Zo{G@{I{7״ QEQEQEQп a^"f_ п a^"f_ h_m_0G_m_0Gn(h}W[?h?ˠhˬjW!A=on L?-` "TX}5^gNS)['&/,xRo|0^j]<6w}bqҺ( >*~-d:o| 賜f+_!Wp34쟴pLX+N= wJ$6y6C[n ԉ˚Eݷ ;`k@Q@Q@Q@5j/^"k_^ ^(B((( :,??W ^=vZ,??W ^=[Q@¸|og'tIyU :»TavƩm[>R/,*͏D'(-?#~ѿ Pe(5F@ S1&+/ 5E K^7(@ea`PD'(-?y?> Wǿ[&G᩶`nCTo~#jWzu-k#AUpH{KWtaCd4*B-t:++X-@ƀ`*@YhZeZeck8 P:+ լ"#2iMvLab&WoގaP2ԫA f)XC#X^qܟk [+xÒ7GٙPNz(((Siet@Z5?@j_Lh@QEQEQEQп a^"f_ п a^"f_ hQEQEpt;K~]ejV,AQ$Y"Wz4r-ܥ{ \[GdT^zO[Ӧ_ܼG,564J%\Hր="((((O5,<;x;>*Gˁf2g$.x% Q5uo6״;՞qI4zxDؼ$,qNk,hO5W߽;),#M߂|IiO9lբx Wvyq_Lׅ?S~umV&y [:ƷldwqI(WYV j~ԶZE_]bՇ$_*NG,t .MmbE +#Q@ VZkiֱYXưm4T EQE|M8/tC~&ѧ,e4.ݣ DZoq nH]!- ˶X$V+$R/:0Gjٯ7oL5¿-5`D͍zƀ,__PjU-mo :#zV x]&Oڍ^@3k$8zw&Q x_LQ@:3 uW=RѮOգfF)GR s!7|k?ßZ~8eM6 Sid4@z5?@jOȿ׬_ ( ( ((_x\o3{h_x\o3{ ls4QE ( ( g|iQW6hMH$m.Շ!HV|6EkkEط(A0ƽe㢸RJIEg;g.卿|̠`*// :k鶱YXF"ڑtQ@Q@Q@dx>5Ρ!y$-X$m.ջ2ڵ ?cԸfzR$+$U{d5U䟲_?j5zQE|-?a&]q/2iP @{K5{'^/W_5"^4((Eq??eEq??%E ((+4=K<98WkKjDkuisK (YW9: ؙv@_OEcgh_-ߊ=[.t$^B.,2{P1?FUPa&𾳧Gnggd4:xWsZ=Ժ]Z+ѴOdw#22nXd #9( ? kϯث?j_#cv ? ?Rz'4O|%ox7X8ctOjgwEPEPEP^oeއC,4ȏgY*ͷ ,Xi0-Y!zowdvG4Vl)RGAG񶧫xSǖ׺qx ^rm+[vِEm @Ept|{G.]!PsEsRN!:d(XzE@Q@Q@Q@Q@Q@Q@M'hJ+oYi?G7, 4E|_/H#_&Z}[ķ'XU! ((((((?_?_ׯxKE}b//k|*yETQEQEGB%{'O|w7yj@$uk_xW?O_7G)+')+?SYwtP Jj?O_7]Ÿҿ)oZSW5 WwEp k?֣AMg@')+?SYwtP Kj?O7]Ÿ+oZS_u WwEp k?֤?WYƻ(?WYƓAmg?(Amg?Oiֿ3Nֿ3=_Z{E08/Sg Mt k_?hp?4 k??NiƷ`kœ?3`i?M05E?M04š5`+ E Ez\?5s\)?L-)݁s|!)5qu*n}4kHsAěN)QEQEPKLqZL<G<PKzH*attachments/307uiervcq2e87i3hkrf5usunf.jpgJFIF``C     C   " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?S?>// iV4 mb]HPi# 'd ,q“ݿ+??!ӯO4z&;xBX;FNF!"4q˟(xN{?CӒǷF-.lbXuI30wueE܇tHSk~6gIϤoM|-KK)OReķ5VSsY[$`%%oi_4\;~z4W~i_RFT>jB7`+I8{fQP0(((((((((((((((((((((((((((((((((((W1vū]x]D_26ǴYTiG ?A!S]pD;gHU8I\ƙ-w:u)-Vc>À8c++wkc1 ue|gKW񎿧3i CN\zC:~.IPE q43H!1"Fw4u~>vj?U;? 5RO[m鶂Z6_?|g4A>q4odrf{ycoXidfhնEo'7%o~(j}i0u[+ ι-u 5}9goƨ_U}"mkmkGw'E#^xY.yEb5i]؉X0EmaW F;[/kslm%vjVϝPgoƨ_TEg[vj?U;? 5@VϝPgoƨ_TEg[vj?U;? 5@Vϝ>"~v?!Zھ7tAf$0eʒ>e*3@Q_"5?6OH7G<Sdt'<Sdt5?6OH7@]_"5?6OH7G<Sdt'<Sdt5?6OH7@]_"5?6OH7G<Sdt'<Sdt5?6OH7@]_"5?6OH7G<Sdt'<Sdt5?6OH7@]_"5?6OH7T(֏yk?Ɲ+LwvP:q@dQ\ǃYuO h!V.Jȱ2 3ֿϝ +?QgoƨB_Ty[ТW|-~>vj4(?U;? 5Gϝ +?QgoƨB_Ty[ТW|-~>vj4(?U;? 5Gϝ +?QgoƨB_Ty[ТW|-~>vj4(?U;? 5Gϝ +?W5Z\k>45:}^Y-T1'|ƀ;Z+/m+;+]']J<ˬ]ʥ^$u( Z((5/\LtVNVSYDi vWg8bIy kSR+O((((((((((((((>՟O7_U|kZ\A.rld;7;T@e[zu֫wCZͩZKqeBT6#tz4-"=ek4}jko2D*#HiJp}:塚|;M'Pp_QIl(g3 |]ǖ?QÚ?mėzlb.l.ea񔝞FzOjO lXMXOw5m<ҋucD|{voi#uM ]R)P'-*Q޾PxwN|ao]L:t Ir%k0"Rۊ%wV uiOxO_>ԭ#qoIԗI_rL=$S|q{u?_xgNfUխIF?teHK( XYGqQ5=6}YG}z}6eO\p3\~0Ӽi%I}pVխLvq'fN5_ xA{"HoO0HlF82۞Ts@i7kSx×訲jE۲+gkNCpkO9ߍ3xs:Vso凘W3z5ZGXǯi~i4H~TY=My//DXj_MHΕ/.45GmEɰDC7fn:|">i|"/.femY8bsWc|?_z7]zmƱ$vf%b_0|#=3':=k6ǕiWZm="y]m<ՐIE@I5?|'/Yk'z6ILɈ;_4$M@n Sjzw2į#*ea׏~۟h\mY5x:E)uDž@R'tԶX9yɋ>e=:_?Eniq+Aicq՞Cn c} ?mbޛ}\$zo]QEQEQEQEQEQEQEQEQEQEQEQE{iZOko=-ݛ\+ʄaS]]#oWO4ϥ ֳ?{^sVQEQEg_2օg_2օQEQEQEQEQEQEQEQEQEQEQEQEQE??ڳ)+SY^|]Q@x9YST9yX[z)2d>m'{m~vaѾ4zz3خ*%ژ' q}!3/?:o3ƖVM:Wn!,H9H+gOMJ+:W 8kĖ2?c'r?8x+K/~)W7⍎#Kx5(jb12TfR T+w/g7Ŭ > i-|YcH*A۞+ca_jL׾.xj~&l-) Ad%:Ȝ ~Rdɯس~|1?>&-O uZ|OWkҐI"ܴw(,ŒS_ ;_<7fu; i]2 飶C1F@1@WO^ }|Y>>"0K s$ݽ6弥l&0~ojojEׯ\h/ CEYMs4]xrT2rhV]o¿nMoN~E斶 I%iJ~rgN)/n>о$>*|..u ;mkG<]kLщ7T r( sM-?m4O.^趠Ž7IcH?o%(((((((((((((η{AZ5o!Ch((?R+O+?R+O((((((((((((((>՟O7_U/](|46n;o/@Wq~PՕxᇃ~&ZxZ\ox,U`zh?_=? < Ѯ ZTfAἴ\m{Ïkۺ߀ǎÚOtPMlbܿtnr;q\4>61Q-ikl` bch@c+ 7#UFK~+xg+ w.c8C뎆>|=¾熯%Iq8=AhZ>]x[zOn +Tb2:Ơ3 x̺GAx^_]J$Bxݣw,e]YHA W @cIwmAt;Y L|27gZ?h٣Yէxn~2,/떯ˆ" )+?b 7ZgN:ߋK7ə17 둕Sh?_>?>/ع{ڸ/`_]ڗ-'sկgh7ٚߌ~cu +Ž7Icv߳|ǗƖdlZD2Ork(((((((((((((:C5hujѠ(( K?4?&ZЬK?4?&ZР(((((((((((((DCqZ_-MZ+gɅyV9 p)oW?>\xB6^zcr/.//~&m4궾%G*φ5Gᶩ^)&/(Mw^_I{JIi3yO"4TڣoBS\ܦ"i9 ދt5h&pc5xk\ׄc^Pе OŚj0ɫJ6vk(raontf^' V_G7[!}}OLu>0ӵۍ7C /m[.ȄC*#|_> Y1,>3dO1e,m@rv V_G7[!}kzG<5]gB.vj&j~SYqhPdݸnɗRNwKj:eFc$~Ma}ո|~ V_@? (zO>?//t j6nf*֕oA3ºֵ]nZ=bk}e|Y"YK &b@#.dsi<u2'F>yEtSմ |@<4 umN{ȡZEcBo`FN|w-O]Kxڶ{8[ҼPFi !71l8᾿>? +?oB?᾿>? sM-p/o.m/Mg?(Zsm;62i|R8g [:?gi?|1x ioʻ]sizQEQEQEQEQEQEQEQEQEQEQEQEQEg[~η{AZ4QEQE_'DZ_'DZQEQEQEQEQEQEQEQEQEQEQEQEQEWʟj䯪O>Wm~>U埅bed:|WF04s|hСa~_4Ra|{emq:%kB J 08\G>4^2<3Jm? -{kvM+-JѼdY0~y?l|&? ny>w<͛v7gnuiuκ.vI\`m,7##,]فgy9ӿiMF= m BoFpYOYYN|6;+*W"t S>aZ} mLj&ܣ*016j<]]ɯo/7=l{n |*p$mUӆ^hO<*n|Y}ě?teo54^ԍjvDזlD7 >rAA)<| .ovMa<|V&9$#\v Z+?m4O.^趯o?>/ع{ڀ;H?o%g [:(((((((((((((:C5hujѠ(( K?4?&ZЬK?4?&ZР((((((((((((+ߎ?Ox?oNFmw1$u( 06ݹ4R%xSA?qxZSNdt7֣d*ە Xmcu|u;ǟ~ڶZt¯|@Zg]m#X4*@wHX n?fu?|M ];τ^GaSX)O$Ȟ[|rq{U6w~2G&|DomRbS hlf(~Q W _VQ@)~Q W _VUjPluүf8Fr,b 88|Oگݜ-m:@nrNxPHEr[{+50i"mtۿt P34d#|qA'GjiӤ'U▟z.He\U 5xY_@ W G0/\.E}YE| W G0/\.E}YE| W G0/\.E}YE| W ^?X:GY|s6%MeiDrm]ۈ`C+{/ߊ<Kw&Lj,=CǝtMqfLE=#@%;q^h?t? iK B(ci%idڃݛ+n((((i:4ç,K;<33O$_)Þ<>)x LWhW'J6dF8Ѩ;dhXdR*x tocL5mRnm/mtr?A<[&O/\xHg?^tHL*2~Ft ~XU^C^Bvh8*A@((((((((((((((η{AZ5o!Ch((?R+O+?R+O((((((((((|S akF8ʹafq~=m-g|I+DnMA!V(A 2NX |ah9Hx~z5+cB2O+nqw}O~":ۑbFVX׶=OxoᏆm<;--6V}=Ky$h ( ( (Kg][O4i//.8HbE,~_; ~Gh Bsc?o'wf 5_h_x{O &FӲ?4Ng+c i?_6R[^?iKiz 11;I9̄WQEQEQEQEQEQESUl.Mԭ!!k{[4l 2 H 5v}<|q]j?o6iҿ$b~+~N?tq+ŞѼuO!ӭmR쮓tsFG#pG#4oq42(t6 dGPGz+{czn }H/\_!9QEQEQEQEQEQEQEQEQEQEQEQEQEg[~η{AZ4QEQE_'DZ_'DZQEQEQEQEQEQEQEQEp?>:>: ctN?1 ɠsfh S|?y]|VUނʲ9{۞RG|#!A \oR kPY#_DO_%!{i[-#u^E_-|i@}?z`h;yt-&G$cqC DP0@8TPEPEPEPEP_׷s'xWMko؍iGXgk k㽗VdPI[J@L.VN[B1X?߂ _~ 4>Yf27>i ׈U ea5؞.`2K{(((((((((((( ״գYh?9F ( (3/ҿkBEYwpZsq 5R$@ '?5h1dG0T Z/ aY>E?U|#CV(oOjcG,բ*:J+_Q '?5h1dG0T Z/ aY>E?U|#CV*+lm;{xP,TE%g&SWogZ#[izqus{0ٕ%c1gx]|EUE^<+5Ÿ k:+vfaP@ eA{٫RsoxR-43s E?U|#CV(oOjcG,բ*:J+_Q '?5h1Y>E?U|gqχzxG[M`7RJ 3 I%~ec|8Q|G7? ~\KU0pA+Q49@WA5ZPs㖑av,{]W,բ*:J+_Q '?5h1dG0Uըӯm*&dL*H QEQEQEQYt-m=kOӧd㉊1c@W7 '?5h1Ojc@% Z/ a_PIEs|#CV?dG0Thc[Y]izšu]LwPz2yg>2񙢴imSb2qS'\8u_}_W>~i~n0,֕x*(HPɞ@ J+OkXk~ 6H%pH"+YrI*9<Y>E?UtW7 '?5h1Ojc@% Z/ a_PIEs|#CV?dG0TQ\,բ*Y>E?UtW7 '?5h1Ojc@% Z/ a_PIEs|#CV?dG0TQT^[N{o[WεdL*HQEQEQEo!Ck:C5hEPEPU1ƛ_]rU1ƛ4;rSstüg/%:7?_EQ@:üg/%:7?G;rSsuU~n|X?k(޳Gž!ԴZuZjJ`B_y]~v,Ā}3]N};xsMק4//K+2 9Rڿ?9)ѿ"~1o{+kAw.K%p&Ab4؋ź_;Y~&:do7ײ^["1m Lny?9)ѿ+_7ſ|>4\Ee|y\JȐv.d(>cU״?4_7Gu̶^_dkvhQf-ˏ挅H*s ;rSstüg/%:7?]'_}k0;=l  .>ux_Jto.wDF(+W~C>Xx 6=Vȕ( w18?߄?&j1k+ Uox$--Ve:++(x_Jto.wDF(_wDFx_Jto.+/g'xwIo|bu%$|7ˈيdE<1}]N}˟~&x 6]uΛgf`Rğw2I_ToOO-^8o/I+sIcr|;N}]x(GDS᷊>N!x!~V(aZ\ w6>ZExԒ]{yӳ̧hC9)ѿ??(7OI_U ǦY@[kzogi?P{X4 6k[=e{Q$΀jJo9)ѿ??MkCC. /-,4A, $  KӼMi+ :Y.6dC#r.2wFhwDFx_Jto.;]^x8#k6 2[%2;?4>\ WY۟mO G?v3]E\ 2 JC啄 % 4N}]y/p?7~4 /5AH43rE7($;9r9aCXj~? ZDzF@mI2k7v`Xy?9)ѿ#ys_!RNմƷahy\@D7 ֯xN^IO//}uki:{l!Bk`w`j9)ѿ??u_,/V.x" jº rHml# rxW iqCh5еN-:>-wpkIpr 22 9)ѿ??|iпm_HGL֧w-3XJ^hw xWS|-Ekڷ'[F&0۬ls*(,NIl?wDFx_Jto.}_|t i:o[HՖiCv=F ov?g^񞛩_; X_Gmsi=2%d-hʿeZu+ogi-j!\#YWֵHx?((( ״գYh?9F ( (>Fɏx4/c;7Kmo#|r>>k{|=fbM?'⇄i0-ƿB-@24$p __D{Q /=(S~G_ ZvCO0x.}zd?N?Ɵo'm}6+81(S}pNMY>o9G,[7g!~0|M%_vϰmE]o|߻m^kcF!><jhݥIcdBI#_D{Q /=(7W煴Kq'8&Vi$Qfj|%S~49RZ0n6m[pY٤LGwn̓ )|=?eG}5W6j#<[#,ިG.ݝpt,[7_D{P4Wmo#|rY>o9@#LbՕc׿_ DŽt _/TC7ugbXŒzZ+?WѯWՕgǍoↃM"o ŞvmKSHZE`,D1@y_|=?eG}_>߲6'% f-_m6A<^^6g巐|y`r8\R?cwWokǗ^'kWt1Hh@ gr:/ /=(k{G@|x_x"jZw#pZ[ kn- <ho*Oʑxz}8–тĩJL r?mo#|rY>o9@bY[q."# S(1ԫy<#??>oKo/O$_c7_D{Q /=(5/'N? ״OWkGkXLy grfV7紺.~&"T͒1+?eGmo#|r>>k{|=TnZk{'}NtWW2@`\(((S}Y_|x(h?Q;ѼO&PYf:ąV 2Cޔ_I^P5_EVeP&B_q-w}⟄^;7ϊ:Jx#yְuc6# _mo#|rY>o9@iVY|<(gb̡C҅1@NѴ a[}/gV\wߎS_D{Q /=( 4"_:u=VzR5^ե`0Jo~m{ߋuxV×B$žzR*Q Amo#|rY>o9@W3 ?Xxm{xxVߴ~v9j+E~,|[AM7a^o=bg#_D{Q /=(G{çJ!]ojkZ,,ŜַE 7xNBd7oB>'x:mk?<'&oKǻU3C$8`F1 /=(k{-ϋZ jrOmmGtmeVٰ 8, ~ƒĿ6f|K{m*b;db?>7FߘY>o9G,[7A;$ dپj :m͖aqk9;%v+6|#W]05C^۩?Xj:Fͼq*ogudIJ@15|=?eGtcs=/? ,,Ѽ'WZN{wzvau7ĊcG#f %eGmo#|rύuׇN>k{|=*x=ψzJL]K[x-"\*m&% K^>ƺV$87;fڍH <k{|=K+}!v}) !۰Ȁ?~:t?^7i- qr,JȨ؇ck{|=RԼ_/~4 V666 d?vP\m剏g[|xaƍ6o.t׈mIQ#A31xw.@>qg1Pc:/Zǡߛx:,~mF={W-|}irtW0Z)v:=Յ}@|[Gl>xoF?BGqg]hRX0 z3zWu}6T)n.%H ๒Id`5Kxw,[7_D{W|<~H.ŧzMT5F59>_̧nI"gMSƿ3|O|qq$׶N u2fs2Beۻrmo#|rY>o9^zׄ߅Go9G,[7K |N񏋾#IbҴK-$bU4 Bh+7+Rz3o9G,[79M3HvSq_*>!ۧxO+:m2,VtOmjаWR eGmo#|rW/ >x:Y8I<"e@@UN?6K7#bm>Do3ހ<_D{Q /=+hx_ `ޅKӵź$HoDϹPp+ kjxf:-g\JwlNx,[7?w6ڹ8z3@e5⸗G-AؼjΣscaknZ((( Pࣶw 7xM#.ʹ)ju He=+:>?*E\$0UE%<h;_D{Q /=+׾~?$|EtxfxbӍos&M#C/Sw$Y_Ѿ'>8גk çZGgkh兺|9T!v2ݹv ?Y>o9G,[7UmGkϣ4Ψog$bx%PS|c۟+״LM0#Xɯh1!ͺtGǭy,[7_D{W>'x[1iZGYim1gi*}!4ywW˕B=_42/m熯-4kE?yv-c7t 0Z<'_D{Q /=+~xU/[ES10D@*]%'v%<6^a%隹Q+V/LJ84,[7_D{Wo$q;)p@8gMo9^zׄ߅Go9_`@|=?eG}E|.gɬi~|g}ʦ@r{{Hx?((( ״գYh?9F ( (>Fɏx4/W esϪxE]"=J՗RbdIw|2FZo⷇"𯋴u~apX$L ר'x_Jto.:/hX|LN=OúΒC 9*FNhx_ s4w'ӮiKXɸfV^C=YN}]mB>!h?м-&tIԴkwjTXd>StNs5x~G7vzV6~}ym@%ԫP rN}]t|RthRkKyu(Qn-9N'/ jO^xEi:ZޡSΙ՞4<IE2;rSstüg/%:7?@o^+Au7VWI֠^G_g;mdst|#CVwDFx_Jto.%ğ[&kJѵ#G젵m!{H,Πeo.Ta隿㏇ |kpm x~-Y/4XmA{$]'9N}]hxH  E.Bլ:kgĐ\M77͂k+_9\լ5~)_xj JfeѳcU‡$]N}U ߊ4 i^8D4mJO`o%&Y#e0"t`CtNvY|3$M}OOo-љ%hF # i\?9)ѿA随/Zf a;؆QeqOJ {#'x['omRab9ǥz>i gt疲̱+1 3x5yGo_?;M5k{U |HhGBm펿GkR5۝F7GěFQu95x¾qIu|V@3]EIu'-䘳91w;0(??9)ѿCjV^:[} =.Z{M")RT+ WR\ׇ|ڧ9|WYZ\XYԴ0N(TC~k?˜ym9$üg/%:7?G;rSst>.ռ] լ[qamH#gCgi'C%x֤iYT"=c 9rO+?9)ѿ+>VT(usCK܏^,úg>]:fe㥽ѠCw"-BРU~U*U? |.exk^5>=ίdlb]] m.x_Jto.wDF~$[@k?巇Z$O׼b4BY傆`A"xLzshk5 rw!$NNJqN}]t^м4 (;/ ͫX@To/*Q*^uؑ&1]NA];rSsu O~ -?$:[(YbO8(((]kNK>k+~ 7^߂lo$řy ل~iE'꿰Gɡi}&(Qՙ@&??go''uN·8,x/Yxomh'j4*eKuPs(23_Js^Noj^eiqcgRX;yDϓ ct8-cҍVNZɒʁFo_־ A]/+ W8 %|meV}]{[MF *b9q{׏|!M%߇GۯK3B"l=.j#,1I$S#+9[)]f|jVWs̑Cf2` |w隕F{mK֭HbTU ;B#9UTT%ᗃazL0h_G:tj5v\(o |o8>W×^";nXn  -PA,rpwDF~$[@k?巇Z$O׼b4BY傆`A"xLzshk5 rw!$NNJqN}]t^м4 (;/ ͫX@To/*Q*^ '?5h1̟+)7[? Yj~T$g {3DѐG(3v ',$LDpiܲ嶃gx$(fg'j4,բ*Y>E?Ux;rSstüg/%:7?@ '?5h1Ojc^3]N} Z/ a_Wüg/%:7?G;rSst|#CV?dG0U?N}]sMR*'Y#k!W|1S/~_x+C=,Slno޺(((η{AZ5o!Ch((?R+O+?R+O((((((((((((((((((({ yHaK0UEIIE|ΏKo|f2cx~bsڗY}7aȇd?$-<`{?K-;^<񎝡;.謞C-ÞcLÌd.s^ iGSQx^mQ,P#sF=r4zΏNhLb;xrpê]G~ǾF.ãچuڤbUb- 8ݰ⾁9 9G<)ťhZ\" khngcfPh7Gɩ{]Lb$2 srExG?u-֋|PGr\@:0RGx@QEQEQEQEQEQEQEg[~η{AZ4QEQE_'DZ_'DZQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQIk翊_WŸ#vߏfR/ *w㪝bYsеO_s368%,c1'ھw?j!H|7[2}Ct>|.>|% |9?uSi.p\F{^1 ?g +\x̤`.A=4}Q@Q@Q@'~^~M~X޽>cwDdЁX!O|}|RF &uirħYO  @ʮXR0Ak ?h5h~|Ji4)ú余? v` ,@>Ѣ(((((((:C5hujѠ(( K?4?&ZЬK?4?&ZР((((((((((((((_oZ牓R3,ɏ; ^d=hNnP^뎇$M)7 @Mx>h3k~,*/y$矔#,qŒWW?.Ziᖳ.@3MBs|p(IMm{⏈_έ{D6H) m- PDQW2'@\~.yx6iٰGf>|SE=+<3h@},cS]QEQEQEq>-G/|UmrBmF{|GG88Ux@sČQFK17]Zÿ٪Těߣhݙ`8"|2̻_+hto']4=aY~V^4<{(F,O%I$I$~_?g/+yQX׌uBC9ϗ@jqb7WQEQEQEQE||\KO_\]|H 1j""ChEr ne6V[Đ1E_'"OO ݄>ϝ~ѱVQEQEQEi?ߏ xHLfE̷sѓѰ {(?C}EAz^6Hb |ŀro+(5 ooךIQƩkϟK.b@+zW@h6hS݌7IĶ̍AV@EPEPEPEPEPEPujѬ״գ@Q@Q@~i_LY~i_L@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@W|h|:mbacq6~x=7(7#<%giv˺{B !>V?ho#K?|/]A-r#dtZ>;kV$w">b/%twXF|^+_jf}i^0>~4б4Ⱦǣ[?6aѪ<{W36ۓ߾dl*yfiҭOҴe  1(쨠U_GV>G<h.#ogˇ̌3 c ((((;in.%H K+TP ,Is_ x+-G_bĚU[m6b>fp~ _sVo?50Lfۧ$n_onq ÑW#^./Ua>n:A9 '"YFelCץ_g]*.5jm>*$-NRr, u9bXQEQEQEQEmgkn: &ћp ( ( ( ( (3?{^sVg[~((ԿJe ԿJe ((((((((((χM,lLs$5_;,<'>" H-gS0/t)/nb ;5Y5??o~ |-5^.6̳3^"qԸ.M#\x%]':fnk S_Lx?}ãx_BӼ=KKx@OsTY|9"'?.9Skվ ? K xRM}y|CyJ1LMWQ@Q@Q@Q@Q@Q@p>6/nSnL\L"1̎qv8濴oe66ӏGKH w&w[o~!|M=xg"+(V|v-C-K4Z߁- ū}BE_(s}/冁*El#[XD#%~II$kb(((((+߶/Ɵ~HA"kUb+?hP $fY>-[zVc|<A\ki/25{gٟDQEQEQEQEW|`>|M) KEF{|lV'_ZoxEWK?n>oUtsUts?g_"HW𶼟+ev ÑѰJ?e |}y4ai'>-<_]~i$k-I2#\l`(pVh^)¢Q' Q]RA%u!O6QNS'33Hv?*/?T^WOyx 9G;GOr>Uh^)¢Q'W$'hF4˞?lGc}cKݫwNF(#ov?*/?T^|lG?m Iwڧ$ԯ.sʥOy,q+_߷|K~M3Z_|J>(dG (Q`a@ [Oyx 9G;GOrq5p?C݇UW_h ++._dLi%*hzUخ $.D'}u_)=?g,ۚw;GOrv?*/}UE|'ŀ O'&ia1A/n'c( \bô~ /Q{(h^)¢WTPʿ?T^??痊U;GOr{~W O`WLQ%eIIrF'+OwGj(imK⺷{t:22 }+]/&q?dGR /@3B14t( / л _My7_?w_ Ʋrc$L1%Xn+<j+8jMgoAaxCmF&rcމ83 @T|+k^'D#Biʃzrt tϽ+~07>0xú-ïWZ md)h܆;I,AO?A6ouϣMJ6:rIͯC;JIsP ^wI? OL"]_Ù>] Vk|wy*b~I(*FL?k~2 x?_[]CSh%[Qw Q.h/ л _Mxg'bkN:;wNJܿ1b-GUXVFFʟp ߈>/ߍ0_Xe΢YMxK] #3|?xg'bh ?.?[P ^wI? Ogoa&Ǭ(P*(Ͳ+kJ/cƾ(( K?4?&ZЬK?4?&ZР[ɌOzmJg |a)cO4 _ʭWV_ p*Ț˨@oKFF:h4-k _3@__ [hZfk Z¾' '6CjfCgO/;>ץy5F_khе+zK9K=¾$`,olgʌ+˨8By$ku#_߇;S0?ڻ$mǑ/Vе+?}V~j0}ޖ_g'ʞIqߏ3JO?<?O\Ѵ{mĈ4o:&my.2X3sb oCѡk_W?h4-k _3@__ [hZfk Z¾W?}Bֿ4|OR%;}s-f[hZf_/ zo|%c5zW3(U\s@QE?ٟ&D+;ƾ'=jEǏm3_4KkԴ{FX.G=(*+k Z¾ oCѡk_WBֿ4[hZf6 ~~ x7Ɨt/[\fTfrJrF0Mtɖ~|m1kM4T T8g oCѡk_W?h4-k _3@ѼAfk \26Ժfʁ2&d'#Fva|+M#W>:$RD;qk Z¾ oCѡk_WSVk)΃gRN,q̫F|Vb ;ߴoe}7~W:>\G$q!n|ÒY Syk Z¾ oCѡk_Wn֡xJm^5#Of87ɲUie$%f O־@е+?}诐?h4-k _3G5F_khO&OF1g5F_kk? =gkڥ׎ҦYV7]@ W>Sz~Y|75e|w+5M#Hj_+=")O}2GvrB 4%5F_khе+}E| oCѡk_W?h4-k _3@_ל|vU]\:FkmyC"nPx?5F_khе+\a 7mگOhmƗ eu*; HcorsX<u_.D]Sys!vuh$<;Ek Z¾ oCѡk_WxwO:>W^-WVg ~fbq^  ꊿݳn-y1E@е+?}诐?h4-k _3G5F_khOwGjе+r?[VOMwm#EPwb8h(>T?dGRn#?e?&>'o =b/݅ ċMQ_ދM@`Q_Š_"l?E~?sz/6E}^'w-)čxZQ$KidUT;C"n 灊Q_ދMG(oE&%C^q?4/ iX.4u|7 "ݓ!a,I#5Z|γjO{; KEXI:1>oΪȤFAWG7gQ +(`f_hZ[[mZ?"/jCYFFbn/9k'No.񝟅Ki,ipv?(cPKc5Š_"l?E~?sz/6Ezd .OsM;'Uw!.-l)ɵ Y$rIO |=cxvŤk{/K>$#93I| +(`D(oE&WG7gPWl9?"Q_ދM@%c_CWv} 㦟-~:Z-]IfwҾ(( K?4?&ZЬK?4?&ZРY1__y X?%m}M_-N~'=?N6Y~֟*Y"k.5/е+zįg/)~'^[Z\_pZcnjtc'7WgS?;oj\k-캊O$Vy@A#bwF.s@q oCѡk_W?h4-k _3^㿍Zπ[~sIJ"شѩ60ykib; ri|B׃bit{ .&p@3̿h4-k _3G5F_kkҾ5@Ꮛ? 4o z֓s=]X]M>,1"Ĉř¡Ij,Z.x{J4sz6OYŵV^]޸mZ!fVF(h4-k _3G5F_kk1xUx U5߈mt=VƄJܬ CvZtyt%<8!KN+MA+oFW/vC ʋwt45F_khе+}_2T/{<)<;i6ise{q$ XZDT7Ms_?}Bֿ52慥{O\g]^+llCqeΝ3mFؤFrCuCYet/COD>5NϵE!d;v'9k Z¾ oCѡk_WOQ|N _fc⻍%!y<._%iY#;bY;>#x6_is$ojmmGm2ɺ(~0?}8K| o~ok0ޭ鸌Ź"W{W?j4iK})uּEonJ v0Ɉs(%n:\]7V^k# Xt${ (k֯?\xY5#DKGjՂ_sҾ⯔8~ 7%f[hZfk Z¾׬Z~_ o>0K(igY$WKb=Đ%w2vosGឧ_0?Gt? %<3iڴwYae6|0r?}Bֿ5v[ ,?oS)cHI68B$ c U ۪x=3FNxu-{.`}O06ܱ P[hZfk Z¾ףx+W/ ivTѪkRmbGeA n ѵsW]k=S\u 4?zP"Xэn%DIe3n3O˂?}Bֿ5v5t"?iu_!u=} pT5u}.|8$t[=+Fմk{T6-uq,FzxCfi V⾅sgE0H A]]7fįo_ f[hZfk Z¾׭xo??5Ox^{:מ !XG4lV8 T͏V_94?x;kA\IMnLr $ $;k Z¾ oCѡk_W/xG*x] FZпX䵒!|Վ9y t 7*׉>Ϣ|k{[hjӧMz%w 4L.0eއ$z?k Z¾ oCѡk_WoBgP^ҴZ÷zZ% uglXIuXCpřԀ+O]Nt-"uZEɁ ۾kțp0nx_5F_khе+{aе+?}?SMK_lg,۳j>^?xok Z¾ oCѡk_W/~j:׀|%wM6{8Cb"n6_^xkY𦧩 Qŵ֙ o LXI#x5F_kk}߈mOjxGNGnh&*31^3k}maٙ#Ͳ;Tg ZG~/؛Ơ(a?s\ h<#y .l-Y@LOٌHj`DI~6u?cqFxQ=hXbv6g%U~Q yE~?sz/6El9?"o_>!CO4O.l&s[$46bI!ڛCm??%񝆨#K{7^ o H)'EcD,K@p WG7gQ ++>.о>XX9iHMH fy$r_(\|=fo^R_xM+A6Ay50ʲ# rl9?"Q_ދM^N 1÷z{=> xuߴ 062ed i'Я>:i2?íڥԟgpxN00=+ZFm((gje6MO36,t܌sV//Y隝{Օµ(I_± EAЕ.$?w|AI?PU_-N~'=?N6e?rh? x7/wxsS?4AdO%WtS0x]xStE:)&Hw$nbབྷ|ExZ|C[Ic٠WY9'Me7)R2k`.Z3ZHhC]ɤ QQ%lbafd$U_,!h iH4h-nJo$򝻢tlc/p 6Vp 6V0|͙^M@m O@m O|O-cyhZNncJm cyF$"lxH]ƹh:Z]&BSߖAC+??? U??? Urs/ͤ|I񞱯L:֕mkFw/pLʙ `kp 6Vp 6V|q;sƗ ,WCiQh ^i[I#mA{$]Nc9hcV|1f= XcZkgE!PmW"3Z3Z_4 sV!G4y5]2N ϿB069''+ ወtMCF0-)Y@5zϊ~ n]^%im3:30dmA5- -[$Te2Okø~_«S5~|$񽧌<-^"Kx/nur :G^G{sAk7Ge?hW?fxI̹.(|=躇 ^FI Jk'em2szEoqx/5gGH=Mfdv\wRVmc:&跍k+XRf`iY%e3Z3Zd[,L \ Q`:k RxwkUj~wkUj~=ſ뺦{-GJ58S[rC>0}1@Egf\ZsAk7@!~ڟ;VqN=?ZB1oyki6g7Dq A;_ZQc_v)O|Mf֮4W:l]qCVdP&OxYv.4¯֟f<-oOa|Bᮽض4ˬ&_+q;32IMhf*_uu~>v.4󗇿l> ״//E/S6坷9T3nI$jO '/%ҥm N{*|]ih_ϝ ?|qd~Ǘ~&:I?'o4+xFe~ǺG%<e Lk}s#27$y5O*|]ih_ϝ ?xoZz<-k:S*Yn,b-9?tGߴu? /t{G׮taT]ٓvb_ϝ ?R/aψWء;J[q53-R9^u/KIk6i$Z U0s7WLk((PKʾ]SPKzH*attachments/73cb25jd9ogc6d1iv7cp7dsog3.jpgJFIF``C     C   `" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?7m qN#9ȥVʰ M\ XoV;ZFn57hK7.FǕE;pCBF#@;M!F=iVL O#*-sR"xZv"'q#߭1q92<|4YaUc؏ƙK`z2cMB'q pGҰf@8ǷZ 0G[P#IkA"c :zĜMcbXp9qS$1'́@+ГG*V*8'SҚQq;SHEaqȢ)i 5ClMך`8+zT\zYI]8= UF sʓ Eآ"v"gY#lg#,Qٜs=آnnB3sz.i$^*9c<j@r=)Zv}(.vn}i0mǷ-<݆G .xqq( ĞH_SHhxf* %"#E0O„2@4n(9E*qEPO'}0B=)|HT8iMxRr34'0v'+ E D$ Pzv>җ9tgҦ9J'ƀ G?Z"SHn<ҫu = -u46g}Uzi~bK~t! `T;W5&A㏭G ҆&rz~Cu*[tD9XqH Iޠ tEH n9Ddl=i@UH?Zvw 5 H<03@6;iܪ#1ewhPp? !~OF=(@8TiTvOgހ6FBtbD9b;R 0;NzL@0T.J1B iŶ`Ԁ;{llʼn')gz@( Uвcʒ}{Xh*0hᔱ NpҀ.5Ti@ hW$0۷׭ AZ%V$rPz!T" `3vO$8NHN i@^xހ b=i0iȀ/c@ \8)=Hm9 hUAȧ*=y(# $@9S sK `ڞsl` O-{@]I9NSJSM2T͜"vڞ&X5Tr# h"M1 S;4X4s|֐ e#nM\R3ǁjPF3 V 88 HbM)Gwրy;O' BX U\u׽?l@*$ ;{uǯ~+nqa\S4[$)裖'҅u pCZJsJF;6 gP'@('$J2Q)RT `w JRnFiOH"w@ `~rtO!eL:h\?Zzl H$ :Ԙ {PpXw2px BNz~4Gz+Jh{Rv`aNxҀJCs֜4TW'sBT0^ JM F =I G҅mČп&~ҥM0<քbU>)ɏz@8HUiJ39B&' e}R);shP;8Z30@89=h]]m,@L(lӭ2ķaGf$'ZPbF @>P@F3@4Ї0`8HyTh,:u6Y8ċ"EҢ7HrOaP,^zSUA'ˬNqޘ!1ьkqu=8Ұ\ɧ<T#s }"24zpAC "^p*[h!qEk>ls4,9$$nҰv#rOք6qiTriЯeX 4%7S^W8 !d˴!`*j9k In[Y[T[ct5/WGA|'x5{kmZm2N7KgڻcW·7Q5k fHtL=8'5!s߼eþvwm, Zm3's3m<9sgX1 e"yT_uO_|g喁^;f-VfH?w>h%w-ydGy7Kӿ)-ŽŖgldWԿ |3s~ZMׯeӵBȮiˌ `Ƌ'Ǐ /:eiբ[8#!#''SgYӴ-Z. Loccb*8WX.t{EO4[Jx |=I]:MVgۃ!6ğ:ϡM#eN=8LPe+}ׄ+G4OŸ\ٗUתkD: xŒ9g6dE#'9l3{uKx7͞5:d:a=2*l>s}I5?4cյ0Ei%_A8ӊ [|<iw_OiHXds]2m~[|]jh/[8vGn+w~5|c[+_wn]͔.-6?1CḘ HIJB``A~kyyvp2A_6gZ߇jz^ǧNhFbAssWx/-ԵqǤA yf ۝M\O,y񬱾ʰzQʾ8=7[S6t; fqƁvUU#eOƩ]kZG"m[ 8$!w@9Ek/͂p %`gX#_IkC smgf;o~xXe8r3'MYYdzMu5A.}QwÖ>_]ILP'g )B2>漎-C̚~2ym#;䂨$l|NK|m,d[E vd0Τ; 9󇅓T~薚 ,>[I,pOR`{n\K|5gX~KmAC#t`Y:vS|F_A<#T-$Y/nZP׊Ba'i#Ӿ1V`co@G0sLw*]i7VOm>7U"|GGOQQV@\~Uv-{~,HF{++fne̲N3ex|%jz-)5_gB,(E wgQܔ!vVbs{M5}ai# [1F>ܪF ǣbknyV\+ z]n S+c,.sk(ųZDb6S@\H[0)Sdw?.*űDA"aO1Q 2Wh8Gdx2t2 OZm~hqxJ6}MIBʹ q~(p⦥D# sǭDbf]o&!ARWw8&6> I_0Ȧ;rp1SIɨ15ܺvrZV!F2>߷nB9Xu 8=⛀uۚ'uI}vo%JMiP G֚]8밉Jnīǭ@hq}i1\wJM+h>H`'G$,'!y}MH`4{SF$G皕]m5 1 ܊kRzI#ȣQ:҈*N0Icq+ .O,,M 9LZ81)0#69Hjӕefoz}Ydt$dst-|OwX:;RFjteshXcN 'lR ִs;3faOΤ<&˷kALdRGE5:䜜t* \IL$aX3MUQ7zFUrH*J,Tq]B~U9 ,A# .\/OLF0)N;hV!$74)gjQp >*Ԋw a#\;~RF~3V{Eg*qDclKy$֤EfV4'`+FPۧr xT?*bm «V+*g8lj1OM<1␠E c$@1ͭST'֐/#PO+&={lnެBނ5LBÚo=HXr:nj.1Y>RwE^8a#FAPs_քB9=$~Xu COqXTOz| ձ&4njf(R>`=xEMO:֭gη C yZ%F(1ی{Ƙ}E)UbFXևx𦛢J4u6Bzd>h?~&M4O 3\e B2ۯV?1aI(c\~@XO6oYXxj[j ]l5/q6uo h>^̩< YH=ǽ}PH9DE 84+1_#?l le,# 9N}+.4AO]k[K:DLFqFG=W `~?R 1 ?>7:a4NAՃ[}+~_GOx[Y}p\]/^߽cQWܪ:c##HBX/?ë JI JQ? uX|=46pOʐǩ5E =>{i,bQr_%biqϷ @{CYmr2JrAuw5uk[Ȋ$d6e+NJ> !]FQ]f$rx?׼dbRrSJ+(,|c>{9F7|0B+: to x:?r163!0>kSUy1Ձl ?h;zOYi~#vm>TF`d G׺x/NЭ=2dv$~66j/"9&@NNsM[6<ǂ<3}OZz 5#I>-?i"ԋT0Z@_һл~^?JSeudjBuAo(Ep8ڳa~4mQ). ul{S aH`;`>~>M}Ư*#u4xw'Ƙ>gi-43W'/ix%@=9ҽAiB>L)?EK]Ae[gӵ[Xˌ`+~$w_•`vny'[HǠ*yD2څFf@ ryn$t nN͉QYqQlF]dsҸXb%I<*(ܹ0(Q3](⑑T$tIt}j¸`zɹoƤpbHjL)b4Ҥ4\In F4ʯ) >8ڋEÎ*8ݣ<jRBUR̛A-t8)U 5iW9`u`wH;YGmS yg1zy3.*YndYbzWrAJ8آRfU @뚒+3ӌStԱ܍~\i\,lG=1R[njPd&HEx.SD&01J!>=E H.J;NOy&ie ;zϻ4n'`gҘzԈYK9Z00&=;ګ+! ~ua2/a\rl8 1$jI$FT;DArZ`\|gZdEcG `bHf9&sǠ+z0:Әeǣc4X.LIUD00On.'S]<~5^XI'Yׯ< Ѽ1'3ڄ <ʗ;roʌ/P"iw($;Jpפ@K1`AbH"_a,}1H;BT`@sR)ݟ4M5`;rG4~~Zb&J۶'#y= $'j<6% HXT[13 vfU9,>"%#ސ qHpr٤T%In1c84&~|ϵ'1 #iG9t1ޔEyb:G68$H%ښ|҈J^{*Wnr)2ޓ8;hQzx|n{/ސ$.I6>&UOzVoFIMڞl`'4})猎.2HbG)sOA5}5!S@Pj۝8?0B(*AtÉHqR;O /~Yޠ|JsAT+y>nT rL<fI9JF=@6G2wt4$%N:Ё)!䜁4ЬSS͜ԈJ]t޵n/mv(VڣG)![2}Ӹ.KS7;UOJ=6aG)~Q} T'`4pː M?6YCƞ$kzrzN4NsLo#V-啼 wcԍ#Z4/Ozhru<,({ҿ D>!ZSqƪuK8Š>oiLj3+x'M)N}0V7q |XNt[iaXIe$@}4 .L,2(Ɍ8>+Sԑy|F \DӚo^NrBԎ)v0U$ vBng;9i%PH@^($SY%gـ{\q4֢Yl$srNB9jc߅bN1ԒP:␮NaҔӽT\'zC)=p nB Z UO7/mHi3WbF*$e=EݲӑQoゾZ[FO=) $tQ)o^~5VHw5$V*뎿Ν UR!wҤ@Cg@8JP",9'֚ SXH'@s <):ɖpmv jiGU봞h(Ь{gR( 41}[vߥ;2I qZMÓ'¬\JK.Q`%V/~o3ATWPʱ>G4X 0:4B O5Uyr9\8MkZAmݷ;ą)8c`=%% 0u S o?akUiUp (Npo9ǩE1[AF|Dp+-p8Bi!w$ǁ1"j"$RSª9 ۗia=_ ?=x+@vkt SOΞ4t%:z*a.Ӻjq4HFWo@gZ ȑ[!ʱkҭ2l@FQ]`SAp~2x3] >_ό6#WR|=tH2a0JFZR11=a^%68Z-mKyl"GGPzVx'XMTɧ:Rsac:z@vza4$ڝsw&H!a҅R/8y@|J8L4TGs1}Ey_xG_ d.n%5<-*UsP|7F)8';5ߴ>oduK'hZF_h@|?ŵ4XT$>?>9# ]^k4B3"Hz#8'k?ƅa&vqMt$|@-{s@N Ϻ>)Dcͫr D Z-Pc |՘h?MKì*H_*B,wΟA,~+Fs:4?U, ~+AUok{M;N'ikks% @b¡i`>p|Qc9|@b2$WV)Кq] yoQ-ny^:mݮ8 >FS !`psK BM99HHV!{9 d-'H7ŏ *XRbj??ֆj}*M #h*̤h* {}FVqrhb >\eAjy;zcڧ`)Zx?.K∥¶:6+pwXO#JaiGHТdG01 Z4r$8#TǹF0ۀzځŐ^zJ4:(98Qө ͘C sj`yӭ5ql*h}FE=CM(4LTA+gOH.I&)Ho}?i/ #xDgz>W9bn{:W P~-{ď9e 6? w@T>YmACҵSOYP&|n 22T]Z__ -hGfO.?{H}?[\ +m$V 퀸WhڝזRjZl3Pǟ8=*[{m?W-x#mf\wj~Yti ^->@ W-ݒg<_@8X"-C2?Wqxrڴ'i\䓁ޠCS y »!koM+HR$ݫ㳍~lHy' x'] qv5!qGҀJQČX'&K} J[~\Ќ"k$By`^sV@ÁHG%G4oSЃ~?-7C>2nϹ>3c]iG"FVVBG<C*'M44meiFYOiȅ93vІ;T5:;$NO;@Clv=DŽIӁ;I>4w 4GjҤH”$>V(CWY7/%?Gnt h>"#g]:yhmF:z]N|^sUo'w >X cXI r=Ѓ*Fr3޸^Ojrk14mZ>dz=k;iVhPr j@HcS?JtH2F0Θ [eJMJcݒW$t0aig_Z;%K $cOBI S6Mlb ![ӽwZWw6O\qO)N1gH><z}j]sLVʿ/<^ƻJ|tXc&V{"׷['P ݹW&HS^irlAKM;T/li[z[FͻA|E3"ՠ:Z) ,r2*U1Ԝ)^tF,wڇRzI/ {R~'sNJ4hjZ\]ZI :ИNN>^X)G1;sywu_”;P.=@5C'rڲQ xSWIe8P?*'#(Nh|54 iSoB8 0P # IL6yoMTu8e^#U ik z>^MCH-aӄ=BBۂ9UW|X9t6=w;lx n~8#zV0twjpFMfGd`AxSW{jcF5e= {D-+N8?,6Ù&# Bώ> x3ľ(<`o w⵰.*9'+d6 ]NĞ Akثu# ExW$t94]瓧N,Ot{>Uq8GT^ǝCV>ԵM.NMӾxGV@ҽ<]Nl!=qT)Z1.#珅f-P=̞-km[@OLap8{.öWC,w&% k$>lrG}{bxZj})?`UI'Zaާ]}gOoz~hڞiokݽQw>vO<'x XӴ0B|OU;Wv#5|EAM(Zk|G`I4#*.Tí)-xz{B^ Os]Iaqɮ`|NhR(}obK Sf"tUoz@meOՎkȍAҼ7ggku[X׹%B)x#$~4zmC ca "m^s4 8$3Mac90Iޕ\ 4ۃ$p$}) O:/ v暋?)?Z5sq@ X Hg PwcEf2=h'&da=FL<T@Y)v1N@1 1ښ?*7c5 *GOjU#H2rqKE(3;SR{g=lA۫\}?V8E*5[qS*ׅ~h5w6n1dx%Fsֺ`8O_ڿ)o2id'Yt/M2 ejχ!n5QpJ_ڣ mHcKQ@M/pJ+ּ;FT{^E 6)yr7O9S«ҴG z'< w#O—s<9G +ydԈZ> x.2X7)ٷ%<yįJ.B]꺙S}$J }߰sFuh[zsTd)sW1xz,xմ(+XO'Ԣ! !b\x'G_5xxnRP\Se?akT R`9zxRA91FԃC>1qREE1g(R|޵ Fp1RGx/'yHFi!sa٠)|GR V zOF#ZSoq҅s=ӭ08 Ƥ6S+5OVuiWY5WVˆGOmJ?5g_<] T&ap/</j3Z%~'Qi]T$nUShQ9Í̺Z1Il+bBWhؓIW-JY{^vݬckNFe+,gL,b0]# ;\a\0>lF:H9nsb)#L_ƞ"|ITF!1hgVᯌM7--ԫcOеv5k}H@@(b{_ |m{5k*ֲ*eV_olK+]oZF$P!WݏEs25D:򯎿o0T~'Zɝr]Ƈ#LczѾ'c}$:^w._Im[|Fs}7~4^[ߦ%-{ 4=}#UK~7cڦOs႟p`s6_.2o/+|EKoD#ܯb߷,ҚACSeab`_"#eOרl6zSKyf3e\hOQ?=ǓS1'Ɵ*8O٧^Z|g!ar! JKiTlck8/+/?Ntg^~An}(Ǩʆy~u A~p^ATAGYSv@㚉 jM~ T'H ӢZ>|6D;<c$΍yӷ^@|G|!w~چ].mSZ5yWy/Z]#N3jZH`,ўbz`>C 4I6HRN0| X?qn³j[نnˎ6:k?^"2iw,-V?Rz\ʖ,ٸ1\C y_zW;t6˳82M<_k5z5KjV0|6,i27q_no;Z Ӝ_PѠin gZ:SƁ]m~iĺtCBoo%_SCۏOk 8ؖ򖬆+Zlxp=p+eYTGoM.f}sVé{~g$#L6\H4U L1S҂v;:՘6=}r-89"@2aC@DlS\)H|*~yM^|q Cm#U~$֑%8zy;٤v,x켢/ l/uqת&rjvn:~O̡CTb/1\%gZ^/+HUB8PZO-ZtkO Ya\>6Yk"6]eTW-Zg/ sMRX%k(Z6CכY״OjZo:E qR?Z9m9Q/8%m$ԁ]׎/> ~/i.tDxߝXc3a[;Mfm!s'2hz|jX2X$(0ii(7zծ\IQrpOEcgYEJ /ln帛~C`[ivp/Xq<t[=?dQS↕j_dd8\"7\|4idF<Zќcx<5j:ÛK{y5 ^ Կg; q^Wj^Ҽ5ugMh&:t~]W,rK-gx= nB# NQCśj:`y |[C=ĂGfBLuWG; ($(>/3zR8=14q4.@?z`? !?0לPK8l:0O4kD$ڟ lS(zJXsJGr?ge ?L$a;LqSsWU}w=Ih#ic?3|4˙vn_z)sҤ԰1Ƥ1-Ig uu8N80*n%"H#\W*N61 )446HV@L<*.@ Cc H9!0sI88u݋'U1@+I~.kn4^FZ0vOZbC|y=D\ ΧwI l-z +٩Yr3Bz&yŽ[q詫Hkh[MOR]Wk%$~}]WO>*$iMʊG$wP\Rā-xleuKό6-&`O9>|TG-Tq]",Bzl a6rp ~*4eOb/>,˴i_p=*zzW\n"7<SeW0vp=a\̧>[v*PwC^& |@)&sŔ<ԍKǪ`q}i$Jpю!rozkIt/E4ӿſ69 8"6p`S](0l1c܏cdh,eVNZin&.(OcҼ?w^Wmb$^cFTDr<1yg xoQ}ė~#ͯr lW ';j|acPLqj#cvi;+Tt䅦QFHc-7! I4;Cngnkc#t$Ep ڢ1N9\ǿZ4-Z$c׽XUʟsQEojtr9=k7HER(| O ;F!9]F00CK}",63Mۜӽ,{r#`1@oX|eucmk,,\_߂gOXp}W?O&.O?2 W_o{ݮ.>PrȊ#Jo?_=< j.4$6Lg8gݲ|'Zuk_\C*4zĻM̰MS|?jC-_' s­v cB]6K.L@^D?e m[LOEd<ȭ$)t2exB`z]W Ǯ構swtJIJO~Z8uE+Գ/c#>ӭ]^o.כ#-m\nkv$lu׸됺OivTUVE`ܚ)nK"T'ow5xdXpsN3Q(>-x:~Jz_i Nh%UPc+~|zr0n:/~^V4 i gy5Kr>s0=$?Lͨ[,r]6yz%icz̿2>clɂ`Ux"d]:rN7?ߠ ϋcpPtX+ι9k?e-:Ec1p$,M{RHB)OaҸ TP)[ڀ yhJl`Эs;HYT~#;[2h֑Biۂ GRnE-vM+8~bo-0:}m <❶\(N*u0бzb`*qMI1g֯$aC .W`rTؖ;Fx8c21sHbBXUРTv۟Z{l~#Fr *Nd|9հp^pש;".NOLKuF?xHP1H+@^&-+0 zi;U1I ,=sU-sv:ڵ ˅Eo^piUKdkզMrYR 95iNImboΜdMmϽPksUC ̅Ak4UpN8_C:s( RzӖS\%=;]WW懿r=G6Mz^=v ʸ~ S sTGÜjr{ZSL,uU05jdbk?6!v.y *?W`դʀPjl;}+6syn?p+xۋi:.2г|_A_Q~em€`Ѽ+5e4RYdvv`25B5۴p XPLhJK/d[ s,򻾵[Jյg{nR={>ǗjπEM.vgp3qP+[o_׉/;He2e?gIJ8W -R%O7VN dA^gouaFXZH3Nh7Md#X,"Fgrxl tu2[sYxiɤj%fWh`cj|9j_{Fgaxa.BE^^Ӿi:Wox/^KvG= ߉>$In徰YK';xbhVL o l9 6VMJ?/9+ =Fݭ'C KRNUoS[Zڥ-qm .R$~!j~\vGFchc'$9^ tKE\ݦȗ%6UyfQK9I/gXL3Fy|q⥿QצIXSb@P}|@TMf ID-sQ i^J#nI#zs]HU#=N$cɼ7&b/HapݕN6gg.dž3p9fu/›'7{qsuf~R= $p[&؀AEǕӈ[ৈqӧկC\A!0}x9o%D*נy2&s lFA,y8tT(*8wq3n'< e$7@8K,m2 Z!14+ hl3})ogR 6Lv+\K{.)~z7j[%mVA/$tj.#,~4^xޠ,OV]̊|q֌\mԚD\ү#h**=icGzx~ 6 {-末l%WY!%jPw${Ps֐mF ;$k~k6z+Y2oE˓u_I-CD2 5s|?00[߼GiGoc\4Ow>"ڄOlMkDEs=Ev%9oxyntIiF.]dcs2;MG&H[~"­}xڤ7R.툡V@q@ + >qwcxL Y>\+F&% ;5Pxzoׯ.WʺfKֻt"x^wRky fyji<1E.k,V0$ԁ8tKNe_+;2{)Xs Zm7R#J.Z8jȋX7 Ҭ'Df$b#.3jwqq\dCcv5`|է7 &.-ִnV/28<[qq^VJ%序K24Bd#:ר4[IY&p -Ԃ`א:RK] kxt{ApN|ַ]z=<rަx%9.qcgFm*xQ' M[y7|Z*gY<΋h.Np>^b'6˭J'|WOtsoe!F1jip0'NJ<7zߌ-..9۠5.wOE/m My.ɰy{ΝscO jZBbԵ+Ea"y8;s;brOe66o **튙x\c`CkiS4F sslc8l%98cj>0=?ҝ B,O]P$xBqHm#!>, }c~&՛O _7$)uzLX~; b+cm%H20=i8HBsH)c:2 \RRYM&#=;1=)W|NFO-zsZQѰ$;V=ہ7AHVc,X?ZOA{pTb=$}𥌁hl70q(B֜vIl}):=M49ZkJ p`ABsӸ PA02ք1IR J>#4y(Sx5,qsNBM84\U ڞ8$(9\Ƃf#%h aJU晴H R)؞i SM3iϽsLsJ=)#Pwç&drqޖ5=ici87i`Tw}-@e1)goS6iZ #Z4Rhgs#o OE׷ }0i?- 4Xl|,b1^؋X `'`J|x'6acӧMB>4|2<|‘׸ hPʹ`z8,_t~l3{N|JoyoaxSn Vwf!cS}Oƥjgiy~p{@ǃ.F|ad$Mm6,'=2zv~$|joXxD%޴? xCv:U_wR=G}ցs)WZ۞HJF]}{Rϊ:0$@qUiHo<:8:״.IΜO=3H_u*I=$4]YJ_#s}!⽝6}E|w j {{]_@hXv͊$G$+6O83dd{zb(%R b(*dTsyʦW#ғe9~c jfZrpO`zPYqHI"gic9=hpIR0p뎆Tx=)QȠ8 cBsjUE@ =JMyEb{T/ uɪhOR'\F֛Al~>n9*Ǯ)T>g_&׀ {gIqWiբivzu%<鄜*+$ā)7 Fh!Boho' !]{jAd '<|o$0IG2{F@[g?ZPOZV~5ydč3܍sƩ$ .νF`1`!NqB@x}CeRּs?\-E?ν 8sN]'H z~AIRe4Ip)T;t#9яP;Ecʞ4+;SB ڞ Ewr1ߚ@+IۜP>oN4 3sL 9\bA!P}`h''ߊz$(rsB> 7ݞ;xCccnH'ˇހ瑌S~*A?JrJ@<dԕJ4<, rFqB.iG9H-ϭm`$Bp:NT=`W.>a>╀1aS*p<`qHM(9i!"FhZQdpE)`dЇ'@ `˒1KPI \=%G dGNKҋ`\=ifSG2G9M@`2OZ@I哖40ӊv'iB0F?Zr140>0 ֠#GLq7nK{$$5#ed}yQHTc* QT`{(~U &I]ݎ 4*IHևeupM#@<ͱHL4sGo&x-^хΛv'VsN1ס_ڰ/>EU;ZU=kMĨAPOO*0$GT3B]~cRFHЪ`~ q)PF H2*>S9J)`x4T=YIQU#iUr…A9 gC qFwg4}h||oSGP"b0uVV#0zrsY`vcc8+I$p4n$2);iB8<ʧnO*y9Q@ j<y(,v9,NqOnq >: eGJ<Xl{w$3σl$TZf)YDIPCԞ):W>xYc";QQ\1t%$Ǩ/2(,M |5/[I4<&3O'KPN(q@ulbaxrLx}ƚ>xDHѢI4ǡ3/&ISvU~[thA?^F hq?KP^xue940HW2 |*Th6 jCu_&-8tē7w~:mEsA54ҭ#NEYG9:1қ/9~BŒƁZxEEWRG Ik k2\ɧqs'<9sҲWោш_بS J *TX>\UXz7#}:RGp|.bO4ݿ $:xwMA@&ǽ4JO\]97U'+O ,c)X/ }ҔʻN&V0l89xҁeX iפM 9Inq0^>;sᯄJkLu~P<(xoJQkCurG)>(A0ckVvJȷM|OP s==c i4(GoZv=vWҮy4ݧғa ~q@O*.AihߜN, @zlr^l:{#SP:fE > % ǿN(?0ϰB?12iUdg@aEEAo@A]ݒB@'Rx|BnbF(#BiH⚯xŔZ@=q K)<4vFq^rRUbG UHT X^x)Dڧ x9Nz iۜcڤvsӵ5psJԀpI9e1)6: ހ 29GE8W>4\>,p١Kx9Q)pSJ$zSK{M6-Fx%VoEfܹH7Hz)|Pz.7ghN1ӕ F}*+sBl cO*!>ԥ1W a6hRaIH@l7ԏʗrdRĀghWNhm3ME"B"gNQNp͞;Xte<3Aue 7s@9[K#lS#I$sKڭS]xϵ$N_^qKi/TdOpc NOy) ~!zr??JpUUgR0=ZlR2\_qX@ 9`iWOMPz04]W<{~4 9 Sb_/+8ISgsڛyg?ΐ.NSZN֞c'94r=騥sU,oPpi=)y:ԋt$4Pzt4SsM Cd8!#ro\P=  w~4RyF}H yဘ8ǧMR}!NKdk~,j' duWXyI#~E@ KsLڨ;OԃbawzR#v@P u0zp'$޼';(OOH!i1'ă@Ai#4%2۱>B/3-[E s 2VS:ӣpUt4 c*OElq{%Qr:fd [ å9xw?68nI41CZ7.6\h*@ m!T "ty=)~1OʘU@\F'jEIZ@NWQx %J$,u,XuE,nd:󏊳 c%waFAy>kMk24.߉1O# oHgm;*m.<,3 #Y1SV*:뚎G_9ch8֕&h._:6ٷ9@'$';s1M`?kJ#>c,͵zQF8cׯJRďUI:dTۈSj@PV z.АO=sM1$i܀Gh ˂qɡd Tm~rzIs\q:tϷ\p*9%X{U\y8啤S9kJ(銆 ghw܏΀$FG'" $#s_F~fI@u@n; R}#Uh8lcCl2n[+>-OM@+;לZ(x=05~{tqwGN՚?/JHHP#"p]0T:f+,[$S@+yW8$Iy6͗9q@\d$Hċ.;gA4AZcQ ۅ/) P lǿ֠s4T` ߊC9L*瞹$iL@͞>,i$r$ ~}, `Ƨ7fl+9ķcV 1s@A;J[(P8 #D[ñ .=z$||`c:kd$w 2q${;qϽ3_ZKv.> IV[s GCPdʾX9:v+b2ܖ<`#lieGϞr4}6Aǵُs;/L @6֚EWR(1>\,rƣTs w>GHz:CZeAΉwk%zZ\ ݇k,YWnqW4Af'H@1GzQu"QTsE,DX=@ LA$nd".$]鈊bd8DCܟ0;PHXd`?QMr^&ʐG=i!?;^NJIX rC~hZ|rHs'Alʁ֦۵#Dr#֐Gq7.QHZYrUA=e Kr2yr`'@NFԋ+y*Gȣ1i"(I0j'mI3m=@ZW;iS|g pIc d)S^8֚#ġO2O8BZ$ڣ'ȏolco7n@!rr~9fҚ6>Aq`M4*Ìbn8'Ԛ ydتvgzQ?.{Յ!z{P]tqHD,}iH#Smb\6OL{TST\ ù iV1OwqVª?TQP ReSgv~ch1ǥH*Rr.4C@9W=;T{J63i)#wǀTpsQVv {S2zC FWR(,J~žFĎV2nîN*fUa[ ]zBV 3OQRG$y,9ӶrF AU;zw q5l8/{;̄!&kU4ak&@x }9i +~_PvsIGU>:*#Nԣv :6'\1xBi: jY;EI4-_ރ"2}e \~P _rU܃P~:o`|+@N6?.mš.g40e+=j_uټkkPW}kJ{yc;r" q,ovBW>MMV#1]n$l')D Nr_Z׾'SZ:~i}) $ZV@>džG0:gW8*w٤?@qϜzk_3RMZm&uH(?)>ڼ DХ֐gxhL2=ZŨ>;(?+>+_~F/ E&vj[կ/㭆 xżO%y2 @ ՘VzWs|]fuKAwf%cdnG|g꭯:i[IyHYql9;sR dֈ:JZQʤ6jÏ'ÿA .D/grڑQIq}O<_ºXV`hKf=3VmEskDZJtҾ#_2O q|!Ų4/9W4_gKgt KT[xeܮBqj_ZĆidF@2>9~7!|{tlԉ6zCmgB?|nu$\yQ6vpzQRi]Iv9 WG4(m4QRGdT{=[74B[I# idoIwN*x`iz!wN:'Fh,3 3MQ׍ 2Gޡ>|cU LF@?_]6w}7]gZ Y4}en Ju@-'A=8ZG vGMh'}ݹ?*ztIb zJ->U60}4o&?dOk u{a4m$ ʂ~?J ]~_]\EAanBlP,ଡ଼냂f5@T_^dy 5x( A;@7S?V2@j?OOw l>ZZ\F1vGmE?.x;SDVn5 )DWkv5qlI#/L4IxGmd*yo8$m v *W[ IVL֞qǹ3;$N=7\Fsq8Nj $c<38*8IzR+0҅$ z 5;; >7 I%{RWwz~z,:t[FbKuF_'Ҫ!܀'c<}*X.30:#m/H=CAե:RN%XF G+Am62hOm:VDFwHo,(`8|S<ϩ$t@l^Fk? RjwI;i#;85\G-|Hb Pfj Jw C1 $hJ;ɉ|O{_;-xSSA.Ѽ/,3+OM!"Ci6jΑz?[ǣ:$؞FԬ<Vs38}*<'yVY09tE -Au|j6kb-V+i-c nnH81e?|6{/ZZ]SOʢ"@;N !RPy=AcϯZ\G?t.}aunh+Ȇ"8%z]3Q>w=VP@"GzѭB3韭 ,>%Hl/R(Ycuar35v $eW|#ӊv O#̎G,~:\|qՃRH$1$azzw{L|= $5oBb#sϙOxO=LJ5|:O+~F{I#)S:t@P=}5  5p#(|Zk}6 ^ H&HIʝSE?Ck mR k1pe"$| g2=j3,ʡq4 OVoum_PkkV@ G9^pFyE!o X:ׇH/t}0nv%F0a޽&`W >Fu4|Mm="F /EMƪ1vuU^HrN; w[v"0cc*BYmm 1+\ Qd-OHomtưx$l_YV+ rK ի{,H# ?ȣA/i?RF[OqYwx/],77I}C4~@VӣvSqoΟ:G<&?|Chz--<=MgmoyPF+ǎ_Knפ^.`4g(Ǡ-8n2/˪遗u%|89Y /k*OjQBA)<t@+15/,Nh&@yiaImN?ƀd:t:B ;=7O2_z@үG.0'N~S^*:CGI ?"v#lFWoq݂sW.ZlwF$/٣^Ҭ~y77{$UCЀmQG:E/;˧hw; CcO\W4~þoi5MOM^q e"m) qbNzŜN?ZI<[@tǟ4ϙl>xJw ZiΚ4"*u^m7º:ZT:4mzu| fw/ RX~@ҧ_xv8u<1=,G_x\xiz]x(27`j|70ceem-kSZDTgfN3E{x[H@yǾagyꝇ:_>1~&xKA[?iQ :Grzb ~,t=O׍`swQ} <0ɹA |,_ H4z?ƥJ J# 6~HvdYngٱDQn{WMῃ^4V!]*-/r<M#MnLaT)dG9^>#>#ҀϿZH(x9ωt7Qj,Pceim[i468'vzXNjچoke=Õ k>*x:"G$Hɻ~(,_OGQtF|K$ѵ]EGclꌂA#;9YS 񭯍< _M%>,Q<]t`q޽ǂ-ݧOΈ-Ww%zN=1QB{$E2nm!wTo>%Q4?it} cy$=rZQ1 Vi)lxI9\+u/933h]<e(cFqĎOmx7a?|Y\_}iZ4q5(]n/c?֚>4x }/cM=Hsc'54JhGSˁ~>9ZNv^'.neX.[A|<; ss_GNG|;n`+E%X5Բm'9SdZB8rz4`GN ڕhRNE }1Mھf|ZrF(ք\gH9 h. g"9Ͻ(\{TTr39w}@$jhҰ%d<49ޗ`ƒ2Ö` ;Ҕ 1Z$s \#m1=Ji9nqJCցw* %}juʒ ҐAxЊ"eeond\R'pR9j-jN<LhEXra]ae$7D4xj#E ETo'8j)f: D `FsBX)15؈F:R:'p֥R ( R] bɅ`ҩ"d!B[#XhPw~n#v"*U=j23`.8LV"蛱|˪x7_1?\PækhVS>QtᲬlJG0Ï BG ^u?nI5-r:>Jz{'wz[ɩ^Hl fOychկGGzыe`8Nԟ? /l܂L`Lyw4hpm<fo`> jhf_) qTC^3;'lJy3gPJ/HTmg ۷b?RkфIS=G5b#&p8d~8*|7X?I+^x7HJ>|;۷.<*좸i 9  ir ']h[(~T7R2},z 슪||?4Dqש,| ~9"PjH~ x&lx?H錋H?%>F2F7sC94;XGO|(;&?uJZYX+ccޜGpEO#\)4 8|1Mg6x]&}֐. 1 5|z.I]lpVj1׊Ua2*X`ߙn^u朧49$zQRWTt9Ɣg( +1$Q}>> Iʟjb`3K36oϧփ W z >{w q=0iR UKgr'8*=RCHHed'š$ bF%>1iڄ&ê3t23d 럭@" q``~FiL%^CXG tցXQwd7Qc8Ӥs}Udr!Zd1`q4J3ճVy4 rNha V2ܜUm LᘩdK-C6)rCl3@QIh:SHJV'zǫżw~ԟ]s&à'J%.v8uy"@,s sqYXHkCBqyր=+H>,KWx{=9[ ?cRx؏mBjhi7i 5៎KdQǺcN?VjIټi?P^Ŏ?/ZD~7:=ІcT?ƶG14|s˱\+}*1w:HΎ?|xcVGm.kUi cdgwg)|qI}1ף#<x5Zk'O9M,dHP{{I*moעtm׊3NjݶM9'W81+Ų*(9]h۞m,=i3^"~(|[b1ùpqa:]Yep>+iGEr ;a8;G+wCeV#UCj|:<gr"wQO'Xc$s׈_|:]|[ol]B5Uz7}b.>*ܜ,lpsRJ!\t/ y?s8,j3ihۇ_20?j=&$$]G6S_zԼjdˏ ڜ'~ xpytP6ɳLsKC2]C|{[C7mRdY+-ק]ē'_pQXl0M8*Hc%K+4ିx>/{qX^ - I־#O2ֺ]U(V=lFP.Bʸ+fVyk_de֜#~4_]m>Mb=coCuG!$9,0Kt(OoE)0qdV/S٬!u-jS$=R{ . 10 dZb=?Ƽ߳\ E$X+ƀ5q@ 㚐14ǵHI+H椌(F*X'13#qB3q+CQj9P8!J˷̬Tެy }ZӸga7_ΚB x }M+G}E^3́֜Ac0uG52nElFvjIBR+{ZkڞP`z+y2q! ȧay&+!!&PL` T^j@(_3s'<L\sh{D}sQȉgsVvӥ.?*UDܩk´Yxj5e0ߢ]^+ᘃ8ڠ)lcC8VgGߧ>k#1K SP_ eu NP0y%g #ڽ| dt#ːbÎqϭy3SE%/!gio DJc=J?hM'Q4ZH4"w^"T3pǭimn0ynne 2o8l08=|Ms WfH$q`,ۍ|'V'ú]Xwn Y>{Haiڌ~֖V;Q"!LxlAZGś}c\In-:L&1cy >U5~"x-fs$GZυZ6~Zes4NKeA@ |}xWBaVB;9Sx[Ǻvin=R KʸJʦĉA\3Yn1oeuA+#3ł8# Qh/a{lH]3Du2g |tWmr(;)6n )fZ-카{&魒8Z2dps q^;C⿈W {~u嵿٭`GK:39!0ozIj,J|G+v1ߵ;.–$7X#$Tb Ǿ+Ӽ+M>_[y#e^Ho?4)-獷# f[;vZΞt6Qu|Y3!2:=1Bb_&6'#zfR3OU08S1@L /D{|ǓeȠ6TB`le$#]$ܚ@ONT7Jd){bwx/]7#޵V'X/ھ@R5cQWöДc5Eؼyc^y6m%q5f(e`8=<=ttuϓ%Oct6 ;w4fѵ綍%@J|GW>`2sDVXk֒^eqv[( ?(|k!VKŖf <Oozl>3h:#TVF\]rpH֦NoB:MlIC&X jO}_ 𭧋_.N?+1=1@4/cXH͕qQy"}Q0Qjէŏ7z<<Ņ8˜8W= Y,((CZ> : bVK%#;,oJ% x֓ [js%iC'GVEs]𝸇T_\ٛ(fRˍ1(®!aom5I`)Kn q@k__2\k>"[x 7b&7.Gh~%M9-&fg$3'W!Q=+̾ xVC.i!u"mzCs\b 8mf"=as?uK_ouwIL1*OгLo#T-,hNw2]rW`ƽ_3զ׬m,? yfgHmeJ|ז{״o6jҝ!ߗ8P]-GjZ D8"ݸM͂N2sڑD_BG\Mmi#pV)'UswƲ.hu;""u 5H3*4@qQ{fz^.nY8*z>{fg.m`F#.:wnr}xx@@Jsc-4Fy>Rf>H>? S sߚzޥ#ة3E)]Kݰkʿe%fAh1/.jpdgi5߲4_{}A2۰Q׃_=|Ե3.jjO%W;*sھ1\:׎qWE":(BMO\]7:).Y IvزoF>eOx~ {XY}PXbV4!skC-?:eN&P[HH0H $ 7ZMƥMA}}N2`Uv' IO:I7uX'dV[2+3 lB\v76UΚl:zYyl.2 OQ^q]m/X{rKSX !msS?֭R:Kmvr_2\iI%ԓ_Zjekp7f[lOU2tar2q'?1E wj 7˞EDZz&J`oYm̑w?/.tV]>v>_Fi?RdIgd}i#I񇆼U{gqXk2t"st885C_!xi hRKKE(@@s?v]]ڬ*e{'kOc+](&[6I?A0JG|+-5Σ q^]e3瑃':W$P2Z4ʊ{#u͗48t2dHUW[]Km.MM\*xdu%#G<`9U68I$kf"vLҸ``}=\σ|$|7zڋ4Tx$SUF~]$XW;0>ю"^H {֕2|߇փAKA#=~T;d\S`r( Gn)5om2㿢5z  8ynj~4v컎H=66OJHj-uYt`6r X'kĺyZS,szbp5"O0t뚑!> ib{]N=Ń\cRx9>9,+vqAl) @*Icޗ si((Ҡ㓺Xp}}jENߝH|/^h8)Ҭ۠q*PrI֡X^5R9ϭJĐFJ:f7@X*>3sOPl8C'L!Y' EV 3May$sZ$"ң'<})'`\AN{ rYsQŸ.[+1E;jH*ByIasԊ?QNs\%sNY!ɨ‚4,z -ry$R. nTS~AV,)lJ9qB94#8 ~) BqH/pA($NNNšFwԻ.I2QC<┣ _?xS>!~ ;P-mR՘Z2?(RKc)g?΀g7'b=>x*:Hp:86iɞҹ^=p$^ O^-|=j޵<-[O\|5YeUPV8q} ~m%u$nm IE~,]F{ukˈPE)(x?2 r1Ҥ5 _<UmF V>+x+xYwp$ Nd>ڽT:_taNFsޣWf Ӱjy$_"8?i/?Z x ;=_XJB:5,(BsNhE*~?^obj{VڮN[.ol ^CJ>)|Qo„"kץ9#1hLU%tgC#?Dmq1ꆷ㟊ھa R !2eTqa~rn ΧIC? |9jZZr6OzGL Jx*x㏋@;zI}8tؼoqWHsduW1'b)S=I'5i+sˇ.xFϧN>0θEze$ś݁⟋?N'^ z! A9?^*"͆M!H|]}wmQ?n>0|]YW,e Җ;ve] Ԋ|_P"^?%4O`WGjMq^m\ f|ȌC@|&n|=N c:S\ZI?xlPu ws?ֲ~.~̞ bt]{ouE I#x -WF^-<; %>/lmɪ`lм2I9%'LsKVjw]mu}iĶ]:Gk}HhRXs:}j1}kj? z\㔱? ?K&6EݾE eEyZI} {]4}|(5*ʹq8!^`'N{J_McB[^)ǧI+݄qmnze8 "€2¬$zab";\qM eJYӟi^,>$()v(}`?)E2WNp.z,hZPd>Ws):u? ~tW3⧊iy/ZYKctOκ~0hα^K{t ns@}ּ쵬0ϋJrv\~9G}Jl {heLo|Qg ڿI$޻?9O 1X\yD+瞍 Yh pI:?K#Z&T3+n҅@$)c 8 4_jhO?X)7cS/anZ+Urr)WT.[jG RH4ȩsS0yR.n =YvBhRPy֜q8 LS`o~~5Ƨ'=jQ2E[8-@EnN󜎙=j}и96zܡBz٘ :J^)`'H̨I+Ԋjiim7G:8ٹcƦQ=d)s8e p{գGJ gi Ȇ$wnidprNzdvvp:8b$#pI 4"v@?O5GT!mY.㶖0 R\u)6ǟA}Ó3iVԤ;D;9#d"wIJ8# 7<|Z_PmkVԤKScj$zЉcc|==imSje$=$=0hwJbF0<;ӊzS$qgKgvet,OZ[?_B%~:PS4 E [FqMe|U2i#k +y&G1c?2'֐F'?1Cm7yԆ=Z~*61dcc*qP $sҐϗ>1ZƓ\@c=:{pI tshi:*ʒpA^ѩ]\t? pDKj8Ϋ#ݺƁXH@QwsqfL",k_[|gKV3x—@j\? ~0[G].:?=jz6#!sMi$'_TQDLNp +~$'HlG899i`CI3=:D0 8qҚ9is # 4M^Ƕˆ\z SƄօn2OzrC|$)\|c﷦(N݅9?C=i&'fFÜM`xǚ}c\aw n*V>Ÿ16f,$iPGbj:ON+埊?.]z_(}[XoGؙ'!F{uڽ+>6?j#Q,͛~GaS޺?-kI&ixu 4ݰ8T߇|'&NOX 2=w8QT 1aڃ$dsm')Q7!P*^y cm~}F#I I C,[<qHJG#F*$Y=)ў3p+1I4BErI8LK>Oj@ Cx ]cn1@l?)S8-X1 M wY"a'rzbб; W?QՆ{Ԋz 4lujS$/Z{֗cN9tРSWD`s#M&EU:ޞ=jmߕ QNBēǥiaݓ$~TָDVbFNiq/F͙H$"ռ:d j;D ALYwBCNŰ8 d?*naǖ֦LFav ދ ۥ ņrGqީ+1OG,*$y~tہ8UGT''5y,cx=)w] շ1xG#b8&3CqI!\dG$3d"UUw > \&<{K8#($'UN-jXdp\608?C6RAI; Z+%6o|ʻFXs\_x\~TZI6]ơX+h C+*m=O})_j ?Jڤ/$nV#ހ>% B P$G>q 5 o.ב5,728RIw8O{{Tk(+5+;.0lRj~W&2G*9,5(8 >)x[[C?h}4Hi%X>2=0Ҕ81qB2@SH.qk< ~mZ#>ƚƻ}\R_2m XuR;0=ERFÎJͷ[2(<{H|h8}yĒ(?:9AN Jv_F0֚f/ܰ jM-jO?[x_?moxdKBJפ6J__zVZ7xڒSW]3c]׈F:@u0R2R? lf֚ tRu쀔pG`E$R =2 O]Z*Ie%=ofXoIpǦ>vqp!s!=l}b93=vSHp? @$>goz,g~|4|7V7 //'9++1* =@޼o|e|S-?N1&m'@'G8FN5O#Zռ/ruD4VV 9tgKӁ:}3J ~!(S K3ܞ:֪hְ3nʸosǸʵȪC@ $evK79#BvzqBH7b}ZI4pĚ HǙ|pǘz~1`M86AwvȨHW*?ϙhAw (1$4ݎB1(@<{gpP#M.1z,R#8v~~!"7,yw"!R<A@Q;qJpOA1@c PbLA@g"U zLr|qۊM8:z67@s24 zZ'S3qր%(Ԟ􋃻TQHǎSd0J@NxD{ܚȔ<{ f4)MN)˅%\[ןƕbsʐsSRG0A@:VriQ@9~pLcOec40 H`vL9-c,1Ґ9{M-',zQlQmPFKb9mQUZ0/=zuQPNkDA,p)"Tp5` K3!R (car L0Č8961@(خ(s؂X@4 ' N )qR 1WkzPT1ӕ@%w]4TQ_q;SF?5++GZ!F|Le) N Hܯ iIV,0d2c=y$DT\Sܒ~b?:0 p'}=ZMqS DXHAFJ1rS62.\=>UprF=qBbʍn ,`w}EN$![zLgb1ӐH;9[G2j]g1!:z{#}!Jd3=A [qЌ2/SQ9PARF@Hq@HҞ@۞?*`7z8BI'ҳD樧4z}Z1 Z5;gvX2U @2$A8_AT5;xMe7:|}fQc:'8? Hlmi b8CO51qy]rLpTS:3T"M \c ֭qyM2oj>+ƣqZ^E5˩e $vE*X쀄eSԁ؊rż7̓K[Uށ@HڣnK A!G]ց OSH GNJq@ n'0Ad4g0x! jP J:p=\{s QۀqHy#w+)w&QQ" ;;TV=IH+\n',}F@jy۟zGsӾbq?f<U ?M'#9pM8 uNM)!?Zq?"@ *#/-xo,;g?2W}C|3ū2hV?ԨLJ@Hj;b݅^޵V\=³ƶ/ʤdxP}3WK92ݎoxoYѴ#^r`4-ʩg-o9#iؘOM`-^$r :8^iaikZqnn̨[ -GFx_F͗cKȟ͕wS Xۮ2;y$Y2pYWz@)=H@sםr}%a*$GY ]H#cW_x@L)cHɜ)n? 9E6IPA|O]wֺi]rV fg*lgz찬puhcP= < ;hSFT3v}MzOoVZq z95jHT @ ܑӃ\SΐnP W c9& r1)ێ?ң7Ap:D'q$sJ6I*$@ TR@*m'1{0?HEPNi8|ߐ@0n0GosB&vUh5?+sKáN2G|B9$A<҆4Q`W** Iy)mMڌqIn,W,rgڀI ,Xg=i1ғ 2p8:q4T~M "zr @r@i-*)-x6R#ҍr4r{4d2f$ u5Z 'i`Fz`AͶ2@DR ަ!< =Q>n'bPȨj-҇c cr O/?y*޹&.̰e=XAp:HG@z)=2I0HwRF=+cwjo1ZPH zRO5ǖȦTqK ZXxVV>$`w=l'q=)G7jj5̄t ,O=Dc.~kFѝmc$q˯ÝqDuv`zDr841^:5qgLw(03a+$ gn} |IK]:Ktȅ*Y2>b|]X|J=>seo5~jL'F G:F5;|!cvguw%p܀Nx>sH˥2/}Ae_611 k<5^iZ=Ʃ:LP. >^h:ŭBK:%̒?t#e-U=9C]Ɨ ]n'b1^r?9NK. ^ݤ\yk"n#5]|C{kz 2,<o_Z>!XkI|bXNZ戚]\,ծn ,_6ҧ+o=@1?$ q nRծOK# `H;{#NA;}X8%a!+8tG×vXx.Ѥ.s$E8ޅxKP{{N$ba"OrH8E9:׼[Ig ޟ{q[ /ּcDů¬YA{sίԷ*2  huS]Pү5[hL+rϵyƏm} Yæ^B38 n 'ѳ֥sfycqmo@OBJ5.75j?kNiZm2a60;]ht?,W_,VgP*۾q+&hz>j:#X&$p8Ԫv'5=g5mPk^|c#p̅? du`w3Zog|]&K* ]e,V,X1ǧ#ҽ8g ܜRCpGG:c0G|r9] Q2;|[ 횊TAHBxN.׺Wl?z)?k])r~Z DҪ[wJ\cy4\O>٦wh2DDĐ6GȣooJsG77nڠ<hC'LKHp{bH zԥ߀ۋ*)MHN@ǵW@͍O0GozO~y]#j]4\c9 jHzkHeޔ3`*q'BpI;ۯaJd xOsQ,t2 z('v@UﲃnU>y_ũOhB9ⷻRW=N;שY *W[|"ռR5[M:amn7<J~h~7ռ\f'HLMy|]p>5èxSgE݋;tXrW_1]]|;-_J ]3Iw^+eqjx*GsYYM Ir{2m  P~I/ھmIm _>A-W6X6bZ8ϔT,sI/-֯LK{yA|2wtRK(/N8ʎkExs~ ִWE,$ HwN NBlⅼQx?-l4H[ V1 r\ ֮XӡUѼG%fKpҠ50m:8#8z]BF2?*> HKR2=uBr 7ฑ~ {\H)݇u?0&b #me&R КA(~hA>ZcƂ`Tn/FnҢRH>#c4Yor*&(r?0 u0c88jXZٶ)=c czb?(QX]bq`M$QlIFK*.*+ޅIܖ, ;i\ fgf^8I1'?:lr9?(''#k~uBB1**ސ$bI|'D}pĒp?3UMR lϽ4U]=ics'U\Ŗ#-ډn$/\~5@Xid HF8I >ҨGb Dn^XL)*C/6;(OZ9|aH)|NWk$~z+aDO'^Oҁrأy+Q--ޛ̸$ 8=OHl!V`A^Gߥ_۱@U9qJCAtܘ#By@}-ޙm(\fPs3үF)3bItPJ(ǘ|jci3F$9Dl=1AJiyH,|z[`#a<a :s9nTݞHJqΈ.R5,;y AzsUV2Q=ܠ\'#89gOZrM!PC6I-Nz) *+jT ׎!!bӌTd;W(@UqI €#Dw]*qcǵJsn>SqWdZn]Čq\7㱌>ITc%qRÕD* 㦒(́fA=RG4.AŇcE$/"m?(5ae6=8֔`!ɦ>Bơv)=qM=CqHJAk 21bz EӰ*}N3̍A搊3"#>¤>mܾp2G4V?I)ٜԄ XU F}!'c2d1Ҥdf{zԅw)NOC@yEý$jc]`aNCx ۷z28b1Zd)zgO‘簡@q6 ɴ:#=9bĞeTK?z\m{NNAo>m é'd* &H^ @T-PžE~s]O1'#V0|G˜ 鱲Y[-j?7O=*M>IV* SvFr Po3ԣ~149 ,iBYH? q)rwc߽$| ^30*v SĽs|㏥"\Zs7w)M5 c8ʂf4FE8l})ܮQŷ:wG7Ζ5!Z#WyPG N@)USj@4Ljl x}; <x; ŁhҢh=j=)9R l~ch CҢxrGOUA8=iPh P '\8$qҙ+=4'NrzӢHG !-RGR8ܑޙojBa,L9悑WySԼ$)I"vxq@^(ػr;{SWb0H8(C1 EW #;>Ĭ$˟ʭKuIԆb VzΑ-[֭hج=ibDs1ptVAc$pqǥ8iEEs$=JJcZ]W#ڕ_#~T]Qc@Ӓo!@V\n)]!D[qҵJ9*`g߭=[x8J iF]@V[҄2AQR$m3㊍del?_j(xNK ~4QU`oAAP+mw9)t"/Q2Qu@-D(&Ɂ$EbEqoG\QE u֣b@7UP},l QEEVe=pj(ݓgƊ)ܛch4 6r{QE+܄ c5"0}EP!rH88GR(@iA Nx |@y`@c(B2w`SF֊(pUF(bvXciu9sE$H CeIHP@\Ey+5,Ic)t3[H4!PITa e ΏK6mߺOpW4QAa[%:F*stQAtL8wJV#R4$^~b(hVHr9`Z(o`IS3B2l8( '(9H G3Vзy02rz} ,C&*L٫\.)VDL䃚(i9vF PJ8IAQ@l z݌tP!D|,n;( 8"2'+gvA>Q@ր#>Q@ rE7B2;E=eTM XEX3sP."é:B6H(Y*T;N~QHPK PKzH<Revisions/0h7q7e2h31b49njdlvs6sd6v4s/rev-1-1408782643962.xmlj中介者模式中介者模式: 用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用从而使其耦合松散,而且可以独立地改变它们之间的交互<?php/** * 中介者模式 * 中介者抽象基类 */abstract class Mediator{ public function send($message, $colleague){ }}<?php/** * 同事基类 * 用于同事之间发送信息 */abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){}}<?php/** * 具体中介者 */class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; }}<?php/** * 具体同事类 * */class ColleagueA extends Colleague{ /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; }}<?php/** * 具体同事类 * */class ColleagueB extends Colleague{ public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; }}/** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); }中介者模式: 用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用从而使其耦合松散,而且可以独立地改变它们之间的交互 <?php /** * 中介者模式 * 中介者抽象基类 */ abstract class Mediator{ public function send($message, $colleague){ } } <?php /** * 同事基类 * 用于同事之间发送信息 */ abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){} } <?php /** * 具体中介者 */ class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; } } <?php /** * 具体同事类 * */ class ColleagueA extends Colleague { /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; } } <?php /** * 具体同事类 * */ class ColleagueB extends Colleague { public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; } } /** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } 画布 19PKáPKzH<Revisions/0h7q7e2h31b49njdlvs6sd6v4s/rev-2-1408782687589.xml中介者模式<?php/** * 中介者模式 * 中介者抽象基类 */abstract class Mediator{ public function send($message, $colleague){ }}<?php/** * 同事基类 * 用于同事之间发送信息 */abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){}}<?php/** * 具体中介者 */class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; }}<?php/** * 具体同事类 * */class ColleagueA extends Colleague{ /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; }}<?php/** * 具体同事类 * */class ColleagueB extends Colleague{ public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; }}/** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } <?php /** * 中介者模式 * 中介者抽象基类 */ abstract class Mediator{ public function send($message, $colleague){ } } <?php /** * 同事基类 * 用于同事之间发送信息 */ abstract class Colleague{ public $mediator; public function Colleague($mediator){ $this->mediator = $mediator; } public function send($message){ $this->mediator->send($message,$this); } public function notify($message){} } <?php /** * 具体中介者 */ class ConcreteMediator extends Mediator{ private $colleagueA; private $colleagueB; public function send($message, $colleague){ if($colleague == $this->colleagueA){ $this->colleagueA->notify($message); }else{ $this->colleagueB->notify($message); } } public function set($colleagueA, $colleagueB){ $this->colleagueA = $colleagueA; $this->colleagueB = $colleagueB; } } <?php /** * 具体同事类 * */ class ColleagueA extends Colleague { /* public function __construct($mediator){ parent:: __construct($mediator); } */ public function notify($message) { echo "ColleagueA Message is :".$message."<br/>"; } } <?php /** * 具体同事类 * */ class ColleagueB extends Colleague { public function notify($message) { echo "ColleagueB Message is :".$message."<br/>"; } } /** * 中介者模式 */ public function actionMediator(){ Yii::import('ext.mediator.*'); $objMediator = new ConcreteMediator(); $objCA = new ColleagueA($objMediator); $objCB = new ColleagueB($objMediator); $objMediator->set($objCA,$objCB); $objCA->send("去吃饭"); $objCB->send("不去"); $objCA->send("那回家"); $objCB->send("不回"); } 画布 19PKr2/PKzH<Revisions/0iiumssmg62im9p55ggfrbk4b4/rev-1-1408863789588.xml备忘录模式代码实例:<?php/** * 发起人角色 */class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); } public function show(){ echo "<br/>State=".$this->state; }}<?php/** * 备忘录角色 */class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; }}<?php/** * 管理角色 */class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; }} /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); }代码实例: <?php /** * 发起人角色 */ class Originator{ public $state; public function createMemento(){ return new Memento($this->state); } public function setMemento(Memento $memento){ $this->state = $memento->getState(); } public function show(){ echo "<br/>State=".$this->state; } } <?php /** * 备忘录角色 */ class Memento{ private $state; public function __construct($state){ $this->state = $state; } public function getState(){ return $this->state; } } <?php /** * 管理角色 */ class Caretaker{ private $memento; public function setMemento($memento){ $this->memento = $memento ; } public function getMemento(){ return $this->memento; } } /** * 备忘录模式 */ public function actionMemento(){ Yii::import('ext.memento.*'); $originator = new Originator(); $originator->state = "ON"; $originator->show(); $caretaker = new Caretaker(); $caretaker->setMemento($originator->createMemento()); $originator->state = "OFF"; $originator->show(); $originator->setMemento($caretaker->getMemento()); $originator->show(); } 画布 24PKVuPKzH<Revisions/13lrno0ou22pncrqu6nv5pivj6/rev-1-1408265436314.xml |适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 画布 11PK!iy PKzH<Revisions/13lrno0ou22pncrqu6nv5pivj6/rev-2-1408265494887.xml适配器模式<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}<?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 画布 11PKPKzH<Revisions/14rdlng7ecgfhsvlcr94rhvpmr/rev-1-1408865922886.xml迭代器模式代码实例: 公交买票<?php /** * 迭代器抽象类 */abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem();}?><?php /** * 具体迭代器类 */class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; }}<?php /** * 聚集抽象类 */abstract class Aggregate{ abstract public function createIterator();}<?php /** * 具体聚集类 */class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } }?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }代码实例: 公交买票 <?php /** * 迭代器抽象类 */ abstract class Iterators{ abstract public function first(); abstract public function second(); abstract public function isDone(); abstract public function currentItem(); } ?> <?php /** * 具体迭代器类 */ class ConcreteIterator extends Iterators{ private $aggregate; public $current = 0; public function __construct(ConcreteAggregate $aggregate){ $this->aggregate = $aggregate; } public function first(){ return $this->aggregate->itemList[0]; } public function second(){ $this->current++; if($this->current < $this->aggregate->count()){ return '下一位'.$this->aggregate->itemList[$this->current].'准备钱<br />'; } } public function isDone(){ return $this->current >= $this->aggregate->count()?true:false; } public function currentItem(){ return $this->aggregate->itemList[$this->current]; } } <?php /** * 聚集抽象类 */ abstract class Aggregate{ abstract public function createIterator(); } <?php /** * 具体聚集类 */ class ConcreteAggregate extends Aggregate{ public $itemList; public function createIterator(){ return new ConcreteIterator(this); } public function count(){ return count($this->itemList); } public function add($item){ $this->itemList[] = $item; } } ?> /** * 迭代器模式 */ public function actionIterator(){ Yii::import('ext.iterator.*'); $aggregate = new ConcreteAggregate(); $aggregate->add('大鸟'); $aggregate->add('小菜'); $aggregate->add('行李'); $aggregate->add('老外'); $aggregate->add('公交内部员工'); $aggregate->add('小偷'); $iterator = new ConcreteIterator($aggregate); $iterator->first(); while(!($iterator->isDone())){ echo $iterator->currentItem().' 请买票<br/>'; echo $iterator->second(); } }画布 25PK]PKzH<Revisions/1gcdblglfb7hr323jqe93argh5/rev-1-1407662907566.xml设计模式创建型模式抽象工厂模式建造者模式工厂方法原型模式单例模式画布 1PKn+PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-10-1408178391228.xml1#设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct);工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。画布 1PK\Z11PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-10-1408260438664.xmlI!设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式swefswef桥接模式 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。分支主题 3分支主题 4画布 1PK lIIPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-11-1408178526654.xml 2设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct);工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。画布 1PKٞ2 2PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-11-1408262734446.xmlJZ设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式swefswef桥接模式组合模式外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。分支主题 3分支主题 4画布 1PKe9JJPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-12-1408187222703.xml4'设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式桥接模式组合模式外观模式装饰模式分支主题 3分支主题 4画布 1PK+-44PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-12-1408263603144.xmlRN设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式swefswef桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。分支主题 3分支主题 4画布 1PKKBVWNRNPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-13-1408264320886.xmlpN设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式swefswef桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。分支主题 3分支主题 4画布 1PKcuNpNPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-14-1408265436297.xmlVC设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。分支主题 3分支主题 4画布 1PKZVVPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-15-1408781865991.xmljl设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PKYjjPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-16-1408781943957.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract clasDs Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PKѧNDPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-17-1408781981114.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PKJGХƥPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-18-1408782014025.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例 <?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。 <?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}<Zxhtml:p/>适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PKC'PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-19-1408782111988.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct); 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例 <?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。 <?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对i$适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PKZ8PKzH<Revisions/1gcdblglfb7hr323jqe93argh5/rev-2-1407666205452.xmlL设计模式创建型模式抽象工厂模式代码实例代码实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 工厂方法原型模式单例模式画布 1PK:8QLPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-20-1408782126824.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct); 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例 <?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。 <?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对~适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能<?php/** * 手机软件 */abstract class PhoneSoft{ public function run(){}}<?php/** * 手机游戏 */class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; }}<?php/** * 手机通讯录 */class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; }}<?php/** * 手机品牌 */abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){}}<?php/** * 苹果 */class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}<?php/** * 诺基亚 */class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能 <?php /** * 手机软件 */ abstract class PhoneSoft{ public function run(){} } <?php /** * 手机游戏 */ class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; } } <?php /** * 手机通讯录 */ class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; } } <?php /** * 手机品牌 */ abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){} } <?php /** * 苹果 */ class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } <?php /** * 诺基亚 */ class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } 组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3分支主题 4画布 1PK+Q.\PKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-21-1408782290895.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到 使用建造者模式主要有一下效果: 1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节 2 每一个Builder都相对独立,而与其他的Builder无关 3 模式所建造的最终产品更易于控制 代码实现: 查看链接主题 class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; } } $config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red', ); // 不使用builder模式 $product = new Product(); $product->setType($config['type']); $product->setPrice($config['price']); $product->setColor($config['color']); 使用builder模式 /*builder类*/ class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; } } $objBuilder = new ProductBuilder($config); $objBuilder->build(); $objProduct = $objBuilder->getProduct(); var_dump($objProduct); 工厂方法工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类针对的是一个产品等级结构一个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类只能创建一个具体产品类的实例<?php /** * 运算抽象类 */abstract class Operator{ public $numA; public $numB; public function getResult(){}}?><?php /** * 加法运算 */class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; }}?><?php /** * 减法运算 */class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; }}?><?php /** * 乘法运算 */class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; }}?><?php /** * 除法运算 */class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; }}?><?php /** * 抽象工厂类 */abstract class Factory{ public function createOperator($numA,$numB){}}?><?php /** * 加法工厂类 */class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); }}?><?php /** * 减法工厂类 */class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); }}?><?php /** * 乘法工厂类 */class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); }}?><?php /** * 除法工厂类 */class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); }}?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }工厂模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类 针对的是一个产品等级结构 一个抽象产品类 可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类只能创建一个具体产品类的实例 <?php /** * 运算抽象类 */ abstract class Operator{ public $numA; public $numB; public function getResult(){} } ?> <?php /** * 加法运算 */ class OperatorAdd extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA + $this->numB; } } ?> <?php /** * 减法运算 */ class OperatorReduce extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA - $this->numB; } } ?> <?php /** * 乘法运算 */ class OperatorMulti extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA * $this->numB; } } ?> <?php /** * 除法运算 */ class OperatorDiv extends Operator{ public function __construct($numA,$numB){ $this->numA = $numA; $this->numB = $numB; } public function getResult(){ return $this->numA / $this->numB; } } ?> <?php /** * 抽象工厂类 */ abstract class Factory{ public function createOperator($numA,$numB){} } ?> <?php /** * 加法工厂类 */ class AddFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorAdd($numA,$numB); } } ?> <?php /** * 减法工厂类 */ class ReduceFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorReduce($numA,$numB); } } ?> <?php /** * 乘法工厂类 */ class MultiFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorMulti($numA,$numB); } } ?> <?php /** * 除法工厂类 */ class DivFactory extends Factory{ public function createOperator($numA,$numB){ return new OperatorDiv($numA,$numB); } } ?> /** * 工厂模式 */ public function actionFactory(){ Yii::import('ext.factory.*',true); $factory = new AddFactory(); $operator = $factory->createOperator(1,2); echo $operator->getResult(); echo '<hr />'; $factory = new ReduceFactory(); $operator = $factory->createOperator(3,2); echo $operator->getResult(); echo '<hr />'; $factory = new MultiFactory(); $operator = $factory->createOperator(5,2); echo $operator->getResult(); echo '<hr />'; $factory = new DivFactory(); $operator = $factory->createOperator(10,2); echo $operator->getResult(); echo '<hr />'; }原型模式原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。<?php/** * 原型模式基类 */interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy();}<?php/** * 原型具体实现类 */class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; }} public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }原型模式通过复制已经存在的实例来返回新的实例,而不是新建实例,并且原型(被复制的实例)是可定制的;原型模式多用于创建复杂的或耗时的实例,这种情况下,复制一个已经存在的实例是程序运行更高效无疑是一种好办法。 概念: 用原型实例创建对象的种类,并通过拷贝这些原型创建的对象 浅拷贝: 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝 深拷贝: 被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。 即深拷贝把要宝贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。 在决定以深拷贝的方式拷贝一个对象的时候,不许决定对间接拷贝的对象采取浅拷贝还是深拷贝还是继续采用深拷贝。 因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。 利用序列化来做深拷贝: 利用序列化来做深拷贝,把对象写到流里的过程是序列化过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌酸菜”过程。 <?php /** * 原型模式基类 */ interface Prototype{ // DO : 深拷贝 public function deepCopy(); // DO : 浅拷贝 public function shallowCopy(); } <?php /** * 原型具体实现类 */ class ConcretePrototype implements Prototype{ private $name; public function __construct($name){ $this->name = $name; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } /** * 浅拷贝 */ public function shallowCopy(){ return clone $this; } /** * 深拷贝 */ public function deepCopy(){ $serialize = serialize($this); $cloneObj = unserialize($serialize); return $cloneObj; } } public function actionPrototype(){ // DO : 原型模式 Yii::import('ext.prototype.*'); $obj = new ConcretePrototype('浅拷贝'); $cloneObj = $obj->shallowCopy(); echo $obj->getName(); echo $cloneObj->getName(); echo '<hr/>'; $obj = new ConcretePrototype('深拷贝'); $cloneObj = $obj->deepCopy(); echo $obj->getName(); echo $cloneObj->getName(); }单例模式单例类:1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。2 拥有一个保存类的实例的静态成员变量3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)4 需要创建__clone()方法防止对象被复制(克隆)为什么要使用单例模式?1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。<?phpclass Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; }}单例类: 1 构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化。 2 拥有一个保存类的实例的静态成员变量 3 拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化) 4 需要创建__clone()方法防止对象被复制(克隆) 为什么要使用单例模式? 1 php的应用主要在于数据库应用,所以一个应用中会存在大量的数据库操作,使用单例模式,则可以避免大量的new操作消耗的资源 2 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。 3 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。 <?php class Single{ public static $_instance; private function __construct(){ } public function __clone(){ trigger_error('Clone is not allow!',E_USER_ERROR); } public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; echo '瀹炰緥鍖�br />'; }else{ echo '鏈疄渚嬪寲<br />'; } return self::$_instance; } } 结构型模式适配器模式适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对适配器可以适配他的父类接口(仅限于对象适配器)代码实现:姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术<?php/** * 球员 */abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ }}<?php/** * 前锋 */class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; }}<?php/** * 中锋 */class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍前锋 */class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; }}<?php/** * 外籍中锋翻译员 */class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); }}适配器中主要角色 目标(Target)角色:定义客户端使用的与特定领域相关的接口,这也就是我们所希望得到的 源(Adaptee)角色:需要进行适配的接口 适配器(Adapter)角色:対Adaptee的接口与Target的接口进行适配;适配器是本模式的核心,适配器把源接口转换成目标接口,此角色为具体类 适配器使用场景 1、你想使用一个已经存在的类,而它的接口不符合你的需求 2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作 3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口(仅限于对象适配器) 代码实现: 姚明在NBA打球,但是不懂英语,需要一个翻译进行翻译之后才能懂得战术 <?php /** * 球员 */ abstract class Player{ public $name; public function __construct($name){ $this->name = $name; } public function attack(){ } public function defense(){ } } <?php /** * 前锋 */ class Forwards extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '前锋'.$this->name.'防守<br/>'; } } <?php /** * 中锋 */ class Center extends Player{ public function __construct($name){ parent::__construct($name); } public function attack(){ echo '中锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '中锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍前锋 */ class ForeignCenter{ private $name; public function __construct($name){ $this->name = $name; } public function attack(){ echo '外籍前锋'.$this->name.'进攻<br/>'; } public function defense(){ echo '外籍前锋'.$this->name.'防守<br/>'; } } <?php /** * 外籍中锋翻译员 */ class Translator extends Player{ public $foreignCenter; public function __construct($name){ $this->foreignCenter = new ForeignCenter($name); } public function attack(){ $this->foreignCenter->attack(); } public function defense(){ $this->foreignCenter->defense(); } } 桥接模式桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能<?php/** * 手机软件 */abstract class PhoneSoft{ public function run(){}}<?php/** * 手机游戏 */class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; }}<?php/** * 手机通讯录 */class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; }}<?php/** * 手机品牌 */abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){}}<?php/** * 苹果 */class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}<?php/** * 诺基亚 */class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); }}桥接模式: 将抽象部分与它的实现部分分离,使他们都可以独立的变化 抽象与它的实现分离,即抽象类和它的派生类用来实现自己的对象 桥接与适配器的关系 桥接属于聚合关系,两者关联 但不继承 适配器属于组成关系,适配者需要继承源 桥接结构图 功能实现: 手机软件和手机品牌功能 <?php /** * 手机软件 */ abstract class PhoneSoft{ public function run(){} } <?php /** * 手机游戏 */ class PhoneGame extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'平台手机游戏'; } } <?php /** * 手机通讯录 */ class PhoneList extends PhoneSoft{ public $name; public function __construct($name){ $this->name = $name; } public function run(){ echo '运行'.$this->name.'手机通讯录'; } } <?php /** * 手机品牌 */ abstract class PhoneBrand{ public $phoneSoft; public function setPhoneSoft($phoneSoft){ $this->phoneSoft = $phoneSoft; } public function run(){} } <?php /** * 苹果 */ class PhoneBrandApple extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } <?php /** * 诺基亚 */ class PhoneBrandNokia extends PhoneBrand{ public function run(){ $this->phoneSoft->run(); } } 组合模式组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的<?php /** * 执行单元 */abstract class Unit{ public function bombardStrength(); }?><?php /** * 弓箭手 */class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; }}<?php /** * 激光大炮 */class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; }}<?php /** * 军队 */class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } }}?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); }组合和聚合都描述一个类长期持有其他类的一个或多个实例的情况。 聚合:被包含对象是容器的核心部分,但是他们也可以被其他对象所包含。聚合关系用一条以空心菱形开头的线来说明。 组合:被包含的对象只能被它的容器所引用。当容器被删除时,它也应该被删除。组合关系的菱形是实心的 <?php /** * 执行单元 */ abstract class Unit{ public function bombardStrength(); } ?> <?php /** * 弓箭手 */ class ArcherUnit extends Unit{ public function bombardStrength(){ return 4; } } <?php /** * 激光大炮 */ class LaserCannonUnit extends Unit{ public function bombardStrength(){ return 10; } } <?php /** * 军队 */ class Arm{ private $units = array(); private $strength = 0; public function addUnit(Unit $unit){ array_push($this->units, $unit); } public function bombardStrength(){ foreach ($this->units as $unit){ $this->strength += $unit->bombardStrength(); } } } ?> /** * 组合模式 */ public function actionCombine(){ $archer = new ArcherUnit; $laserCannon = new LaserCannonUnit; $arm = new Arm; $arm->addUnit($archer); $arm->addUnit($laserCannon); echo $arm->bombardStrength(); } 外观模式 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情;目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合<?php/** * 子类 */class SubSystem1{ public function getMessage(){ echo '子系统1'; }}<?php/** * 子类 */class SubSystem2{ public function getMessage(){ echo '子系统2'; }}<?php/** * 子类 */class SubSystem3{ public function getMessage(){ echo '子系统3'; }}<?php/** * 外观类 */class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); }} public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 外观模式就是让client客户端以一种简单的方式来调用比较复杂的系统来完成一件事情; 目的: 1. 为一个复杂子系统提供简单的接口 2. 减少客户端和子系统的耦合 <?php /** * 子类 */ class SubSystem1{ public function getMessage(){ echo '子系统1'; } } <?php /** * 子类 */ class SubSystem2{ public function getMessage(){ echo '子系统2'; } } <?php /** * 子类 */ class SubSystem3{ public function getMessage(){ echo '子系统3'; } } <?php /** * 外观类 */ class Facade{ public $object1; public $object2; public $object3; public function __construct(){ $this->object1 = new SubSystem1; $this->object2 = new SubSystem2; $this->object3 = new SubSystem3; } public function facade1(){ $this->object1->getMessage(); $this->object2->getMessage(); } public function facade2(){ $this->object2->getMessage(); $this->object3->getMessage(); } } public function actionFacade(){ // DO : 外观模式 Yii::import('ext.facade.*'); $facade = new Facade(); $facade->facade1(); echo '<hr />'; $facade->facade2(); } 装饰模式装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。案例实现:咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能<?php/** * 菜单类 */abstract class Menu{ public $name; abstract public function cost();}<?php/** * 咖啡类 */class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } }<?php/** * 咖啡装饰类 */class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; }}<?php/** * 牛奶类 */class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } }<?php/** * 牛奶类 */class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }装饰者模式: 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 装饰模式是以对客户透明的方式动态地给一个对象附加上更多的职责。这也就是说,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。 装饰模式中主要角色: 抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。 具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。 装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。 装饰模式的优点: 1、比静态继承更灵活; 2、避免在层次结构高层的类有太多的特征 装饰模式的缺点: 1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。 装饰模式适用场景: 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。 3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 案例实现: 咖啡店点餐功能 实现具体点咖啡 加糖/加奶的功能 <?php /** * 菜单类 */ abstract class Menu{ public $name; abstract public function cost(); } <?php /** * 咖啡类 */ class Coffee extends Menu{ public function __construct(){ $this->name = '咖啡'; } public function cost(){ return 1; } } <?php /** * 咖啡装饰类 */ class CoffeeDecorator extends Menu{ public function __construct(){ } public function cost(){ return 0.1; } } <?php /** * 牛奶类 */ class Milk extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '牛奶'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 2; } } <?php /** * 牛奶类 */ class Suger extends CoffeeDecorator{ public $menu; public function __construct($menu){ $this->name = '糖块'; if($menu instanceof Menu){ $this->menu = $menu; } } public function cost(){ return $this->menu->cost() + 3; } } public function actionDecorator(){ // DO : 外观模式 Yii::import('ext.decorator.*'); $coffee = new Coffee(); $coffee = new Milk($coffee); $coffee = new Suger($coffee); echo $coffee->cost(); }分支主题 3行为型模式命令模式命令模式: 一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分开,委派 给不同的对象。 请求的一方发出请求要求执行一个操作;接受的一方受到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收的一方的接口,更 不必知道请求是怎么被接收的,以及操作是否被执行、何时被执行,以及是怎么被执行的。 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法, 负责调用接收者的相应操作。Execute()方法通常叫做执行方法。 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者, 实施和执行请求的方法叫做行动方法。<?php/** *命令接口 */interface Command{ public function execute();}<?php/** *接受者 */class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; }}<?php/** *具体命令 */class ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); }}<?php/** *请求者 */class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); }} /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }命令模式: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分开,委派 给不同的对象。 请求的一方发出请求要求执行一个操作;接受的一方受到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收的一方的接口,更 不必知道请求是怎么被接收的,以及操作是否被执行、何时被执行,以及是怎么被执行的。 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法, 负责调用接收者的相应操作。Execute()方法通常叫做执行方法。 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者, 实施和执行请求的方法叫做行动方法。 <?php /** *命令接口 */ interface Command{ public function execute(); } <?php /** *接受者 */ class Receiver{ private $name; public function __construct($name){ $this->name = $name; } /** *行动方法 */ public function action(){ echo $this->name.'do action'; } } <?php /** *具体命令 */ class ConcreteCommand implements Command{ private $receiver; public function __construct($receiver){ $this->receiver = $receiver; } public function execute(){ $this->receiver->action(); } } <?php /** *请求者 */ class Invoker{ private $command; public function __construct($command){ $this->command = $command; } /** *行动方法 */ public function action(){ $this->command->execute(); } } /** *命令模式 */ public function actionCommand(){ Yii::import('ext.command.*'); $receiver = new Receiver('睡觉'); $command = new ConcreteCommand($receiver); $invoker = new Invoker($command); $invoker->action(); }子主题 2子主题 3子主题 4子主题 5画布 1PK8CfPKzH=Revisions/1gcdblglfb7hr323jqe93argh5/rev-22-1408782352471.xml设计模式创建型模式抽象工厂模式抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类针对的是面向多个产品等级结构多个抽象产品类每个抽象产品类可以派生出多个具体产品类一个抽象工厂类,可以派生出多个具体工厂类每个具体工厂类可以创建多个具体产品类的实例抽象工厂模式: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 针对的是面向多个产品等级结构 多个抽象产品类 每个抽象产品类可以派生出多个具体产品类 一个抽象工厂类,可以派生出多个具体工厂类 每个具体工厂类可以创建多个具体产品类的实例 建造者模式优点:建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易缺点:建造者接口的修改会导致所有执行类的修改以下情况应该使用建造者:1 需要生成的产品对象有复杂的内部结构2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的创建过程中不易得到使用建造者模式主要有一下效果:1 建造者模式的使用使得产品的内部表象可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节2 每一个Builder都相对独立,而与其他的Builder无关3 模式所建造的最终产品更易于控制代码实现:查看链接主题class Product{ public $type = null; public $price = null; public $color = null; public function setType($type){ $this->type = $type; } public function setPrice($price){ $this->price = $price; } public function setColor($color){ $this->color = $color; }}$config = array( 'type' => 'shirt', 'price' => 100, 'color' => 'red',);// 不使用builder模式$product = new Product();$product->setType($config['type']);$product->setPrice($config['price']);$product->setColor($config['color']);使用builder模式/*builder类*/class ProductBuilder{ public $config = null; public $object = null; public function __construct($config){ $this->object = new Product(); $this->config = $config; } public function build(){ $this->object->setType($this->config['type']); $this->object->setPrice($this->config['price']); $this->object->setColor($this->config['color']); } public fuction getProduct(){ return $this->object; }}$objBuilder = new ProductBuilder($config);$objBuilder->build();$objProduct = $objBuilder->getProduct();var_dump($objProduct);优点: 建造者模式可以很好的将一个对象的实现与相关的‘业务’逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易 缺点: 建造者接口的修改会导致所有执行类的修改 以下情况应该使用建造者: 1 需要生成的产品对象有复杂的内部结构 2 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序 3 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品的