原文详见:http://www.ucai.cn/blogdetail/7023?mid=1&f=5

可以在线运行查看效果哦!

《接上文》

5、中介者模式(Mediator) :

用中介对象封装一系列的对象交互,中介使各对象不需要显式地相互引用。类似于邮局,邮寄者和收件者不用自己跑很远路,通过邮局就可以。

好处:简化了对象之间的关系,减少子类的生成。

弊端:中介对象可能变得非常复杂,系统难以维护。

应用场景:不需要显示地建立交互。

代码实现:

<?php

/**
* 优才网公开课示例代码
*
* 中介者模式 Mediator
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} abstract class Mediator { // 中介者角色
abstract public function send($message,$colleague);
} abstract class Colleague { // 抽象对象
private $_mediator = null;
public function __construct($mediator) {
$this->_mediator = $mediator;
}
public function send($message) {
$this->_mediator->send($message,$this);
}
abstract public function notify($message);
} class ConcreteMediator extends Mediator { // 具体中介者角色
private $_colleague1 = null;
private $_colleague2 = null;
public function send($message,$colleague) {
if($colleague == $this->_colleague1) {
$this->_colleague1->notify($message);
} else {
$this->_colleague2->notify($message);
}
}
public function set($colleague1,$colleague2) {
$this->_colleague1 = $colleague1;
$this->_colleague2 = $colleague2;
}
} class Colleague1 extends Colleague { // 具体对象角色
public function notify($message) {
output(sprintf('Colleague-1: %s', $message));
}
} class Colleague2 extends Colleague { // 具体对象角色
public function notify($message) {
output(sprintf('Colleague-2: %s', $message));
}
} class Client { public static function test(){ // client
$objMediator = new ConcreteMediator();
$objC1 = new Colleague1($objMediator);
$objC2 = new Colleague2($objMediator);
$objMediator->set($objC1,$objC2);
$objC1->send("to c2 from c1");
$objC2->send("to c1 from c2"); } } Client::test();

  

6、状态模式(State) :

对象在不同状态下表现出不同的行为。就像女朋友一样,高兴了牵你的手,不高兴了遛狗。在两种状态下变现出不同的行为。

好处:避免if语句实用,方便增加新状态,封装了状态转换规则。

弊端:增加系统类和对象的数量。

应用场景:用于对象的不同功能的转换。

代码实现:

<?php

/**
* 优才网公开课示例代码
*
* 状态模式 State
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} abstract class ILift { //电梯的四个状态
const OPENING_STATE = 1; //门敞状态
const CLOSING_STATE = 2; //门闭状态
const RUNNING_STATE = 3; //运行状态
const STOPPING_STATE = 4; //停止状态; //设置电梯的状态
public abstract function setState($state); //首先电梯门开启动作
public abstract function open(); //电梯门有开启,那当然也就有关闭了
public abstract function close(); //电梯要能上能下,跑起来
public abstract function run(); //电梯还要能停下来
public abstract function stop(); } /**
* 电梯的实现类
*/
class Lift extends ILift { private $state; public function setState($state) {
$this->state = $state;
} //电梯门关闭
public function close() { //电梯在什么状态下才能关闭
switch ($this->state) {
case ILift::OPENING_STATE: //如果是则可以关门,同时修改电梯状态
$this->setState(ILift::CLOSING_STATE);
break;
case ILift::CLOSING_STATE: //如果电梯就是关门状态,则什么都不做
//do nothing;
return ;
break;
case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做
//do nothing;
return ;
break;
case ILift::STOPPING_STATE: //如果是停止状态,本也是关闭的,什么也不做
//do nothing;
return ;
break;
} output('Lift colse'); } //电梯门开启
public function open() {
//电梯在什么状态才能开启
switch($this->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,则什么都不做
//do nothing;
return ;
break;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以开启
$this->setState(ILift::OPENING_STATE);
break;
case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做
//do nothing;
return ;
break;
case ILift::STOPPING_STATE: //停止状态,淡然要开门了
$this->setState(ILift::OPENING_STATE);
break;
}
output('Lift open');
}
///电梯开始跑起来
public function run() {
switch($this->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做
//do nothing;
return ;
break;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以运行
$this->setState(ILift::RUNNING_STATE);
break;
case ILift::RUNNING_STATE: //正在运行状态,则什么都不做
//do nothing;
return ;
break;
case ILift::STOPPING_STATE: //停止状态,可以运行
$this->setState(ILift::RUNNING_STATE);
}
output('Lift run');
} //电梯停止
public function stop() {
switch($this->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做
//do nothing;
return ;
break;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了
$this->setState(ILift::CLOSING_STATE);
break;
case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了
$this->setState(ILift::CLOSING_STATE);
break;
case ILift::STOPPING_STATE: //停止状态,什么都不做
//do nothing;
return ;
break;
}
output('Lift stop');
} } class Client { public static function test() { $lift = new Lift(); //电梯的初始条件应该是停止状态
$lift->setState(ILift::STOPPING_STATE);
//首先是电梯门开启,人进去
$lift->open(); //然后电梯门关闭
$lift->close(); //再然后,电梯跑起来,向上或者向下
$lift->run(); //最后到达目的地,电梯挺下来
$lift->stop(); } } Client::test();

  

<?php

/**
* 优才网公开课示例代码
*
* 状态模式 State
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} /**
*
* 定义一个电梯的接口
*/
abstract class LiftState{ //定义一个环境角色,也就是封装状态的变换引起的功能变化
protected $_context; public function setContext(Context $context){
$this->_context = $context;
} //首先电梯门开启动作
public abstract function open(); //电梯门有开启,那当然也就有关闭了
public abstract function close(); //电梯要能上能下,跑起来
public abstract function run(); //电梯还要能停下来,停不下来那就扯淡了
public abstract function stop(); } /**
* 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
*/
class Context {
//定义出所有的电梯状态
static $openningState = null;
static $closeingState = null;
static $runningState = null;
static $stoppingState = null; public function __construct() {
self::$openningState = new OpenningState();
self::$closeingState = new ClosingState();
self::$runningState = new RunningState();
self::$stoppingState = new StoppingState(); } //定一个当前电梯状态
private $_liftState; public function getLiftState() {
return $this->_liftState;
} public function setLiftState($liftState) {
$this->_liftState = $liftState;
//把当前的环境通知到各个实现类中
$this->_liftState->setContext($this);
} public function open(){
$this->_liftState->open();
} public function close(){
$this->_liftState->close();
} public function run(){
$this->_liftState->run();
} public function stop(){
$this->_liftState->stop();
}
} /**
* 在电梯门开启的状态下能做什么事情
*/
class OpenningState extends LiftState { /**
* 开启当然可以关闭了,我就想测试一下电梯门开关功能
*
*/
public function close() {
//状态修改
$this->_context->setLiftState(Context::$closeingState);
//动作委托为CloseState来执行
$this->_context->getLiftState()->close();
} //打开电梯门
public function open() {
output('lift open...');
}
//门开着电梯就想跑,这电梯,吓死你!
public function run() {
//do nothing;
} //开门还不停止?
public function stop() {
//do nothing;
} } /**
* 电梯门关闭以后,电梯可以做哪些事情
*/
class ClosingState extends LiftState { //电梯门关闭,这是关闭状态要实现的动作
public function close() {
output('lift close...'); }
//电梯门关了再打开,逗你玩呢,那这个允许呀
public function open() {
$this->_context->setLiftState(Context::$openningState); //置为门敞状态
$this->_context->getLiftState()->open();
} //电梯门关了就跑,这是再正常不过了
public function run() {
$this->_context->setLiftState(Context::$runningState); //设置为运行状态;
$this->_context->getLiftState()->run();
} //电梯门关着,我就不按楼层 public function stop() {
$this->_context->setLiftState(Context::$stoppingState); //设置为停止状态;
$this->_context->getLiftState()->stop();
} } /**
* 电梯在运行状态下能做哪些动作
*/
class RunningState extends LiftState { //电梯门关闭?这是肯定了
public function close() {
//do nothing
} //运行的时候开电梯门?你疯了!电梯不会给你开的
public function open() {
//do nothing
} //这是在运行状态下要实现的方法
public function run() {
output('lift run...');
} //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了
public function stop() {
$this->_context->setLiftState(Context::$stoppingState); //环境设置为停止状态;
$this->_context->getLiftState()->stop();
} } /**
* 在停止状态下能做什么事情
*/
class StoppingState extends LiftState { //停止状态关门?电梯门本来就是关着的!
public function close() {
//do nothing;
} //停止状态,开门,那是要的!
public function open() {
$this->_context->setLiftState(Context::$openningState);
$this->_context->getLiftState()->open();
}
//停止状态再跑起来,正常的很
public function run() {
$this->_context->setLiftState(Context::$runningState);
$this->_context->getLiftState()->run();
}
//停止状态是怎么发生的呢?当然是停止方法执行了
public function stop() {
output('lift stop...');
} } /**
* 模拟电梯的动作
*/
class Client { public static function test() {
$context = new Context();
$context->setLiftState(new ClosingState()); $context->open();
$context->close();
$context->run();
$context->stop();
}
} Client::test();

 

7、职责链模式 (Chain of Responsibility):

多个对象有机会处理请求,为请求发送者和接收者解耦。就像银行里的取款机,不管那一台都可以取到钱。

好处:简单化对象隐藏链结构,便于添加新职责节点。

弊端:请求可能没有接受者,或者被多个接收者调用,性能降低。

应用场景:处理多种请求。

代码实现:

 

<?php

/**
* 优才网公开课示例代码
*
* 职责链模式 Chain of Responsibility
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} /**
* 加入在公司里,如果你的请假时间小于0.5天,那么只需要向leader打声招呼就OK了。
  如果0.5<=请假天数<=3天,需要先leader打声招呼,然后部门经理签字。
  如果3<请假天数,需要先leader打声招呼,然后到部门经理签字,最后总经经理确认签字,
如果请假天数超过10天,是任何人都不能批准的。
*/ /**
* 抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继连接(可选)
*
*/
abstract class Handler
{ protected $_handler = null;
protected $_handlerName = null; public function setSuccessor($handler)
{
$this->_handler = $handler;
} protected function _success($request)
{
output(sprintf("%s's request was passed", $request->getName()));
return true;
}
abstract function handleRequest($request);
} /**
* 具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。
*
*/
class ConcreteHandlerLeader extends Handler
{
function __construct($handlerName){
$this->_handlerName = $handlerName;
}
public function handleRequest($request)
{
if($request->getDay() < 0.5) {
output(sprintf('%s was told', $this->_handlerName)); // 已经跟leader招呼了
return $this->_success($request);
}
if ($this->_handler instanceof Handler) {
return $this->_handler->handleRequest($request);
}
}
}
/**
* Manager
*
*/
class ConcreteHandlerManager extends Handler
{
function __construct($handlerName){
$this->_handlerName = $handlerName;
} public function handleRequest($request)
{
if(0.5 <= $request->getDay() && $request->getDay()<=3) {
output(sprintf('%s signed', $this->_handlerName)); // 部门经理签字
return $this->_success($request);
}
if ($this->_handler instanceof Handler) {
return $this->_handler->handleRequest($request);
}
} } class ConcreteHandlerGeneralManager extends Handler
{
function __construct($handlerName){
$this->_handlerName = $handlerName;
} public function handleRequest($request)
{
if(3 < $request->getDay() && $request->getDay() < 10){
output(sprintf('%s signed', $this->_handlerName)); // 总经理签字
return $this->_success($request);
}
if ($this->_handler instanceof Handler) {
return $this->_handler->handleRequest($request);
} else {
output(sprintf('no one can approve request more than 10 days'));
}
} } /**
* 请假申请
*
*/
class Request
{
private $_name;
private $_day;
private $_reason; function __construct($name= '', $day= 0, $reason = ''){
$this->_name = $name;
$this->_day = $day;
$this->_reason = $reason;
} public function setName($name){
$this->_name = $name;
} public function getName(){
return $this->_name;
} public function setDay($day){
$this->_day = $day;
} public function getDay(){
return $this->_day ;
} public function setReason($reason ){
$this->_reason = $reason;
} public function getReason( ){
return $this->_reason;
}
} class Client { public static function test(){ $leader = new ConcreteHandlerLeader('leader');
$manager = new ConcreteHandlerManager('manager');
$generalManager = new ConcreteHandlerGeneralManager('generalManager'); //请求实例
$request = new Request('ucai',4,'休息'); $leader->setSuccessor($manager);
$manager->setSuccessor($generalManager);
$result = $leader->handleRequest($request);
} } Client::test();

  

8、策略模式(Strategy) :

定义一系列算法,把每一个算法封装起来,并且使它们可相互替换。就像篮球队里的球员,场上的和场下休息的。教练可以让场上的下来,也可以让场下的上阵。

好处:定义可重用的一系列算法和行为,并且消除了if else语句。

弊端:调用端必须知道所有策略类。

应用场景:用于对象间的替换。

代码实现:

<?php

/**
* 优才网公开课示例代码
*
* 策略模式 Strategy
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} //策略基类接口 interface IStrategy {
public function OnTheWay();
} class WalkStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上步行');
}
} class RideBickStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上骑自行车');
}
} class CarStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上开车');
}
} //选择策略类Context
class Context {
public function find($strategy) {
$strategy->OnTheWay();
}
} class Client { public static function test(){ $travel = new Context();
$travel->find(new WalkStrategy());
$travel->find(new RideBickStrategy());
$travel->find(new CarStrategy()); } } Client::test();

  

  • 已知模式

1、备忘录模式(Memento):

保存对象在一时刻的状态。亲,还记得“老师来了记得叫我一下”的同桌的他吗?

好处:给用户提供了一种可以恢复状态的机制。

弊端:消耗资源。

应用场景:用于需要保存的数据

代码实现:

<?php

/**
* 优才网公开课示例代码
*
* 备忘录模式 Memento
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/ function output($string) {
echo $string . "\n";
} class Originator { // 发起人(Originator)角色
private $_state;
public function __construct() {
$this->_state = '';
}
public function createMemento() { // 创建备忘录
return new Memento($this->_state);
}
public function restoreMemento(Memento $memento) { // 将发起人恢复到备忘录对象记录的状态上
$this->_state = $memento->getState();
}
public function setState($state) { $this->_state = $state; }
public function getState() { return $this->_state; }
public function showState() {
output($this->_state);
} } class Memento { // 备忘录(Memento)角色
private $_state;
public function __construct($state) {
$this->setState($state);
}
public function getState() { return $this->_state; }
public function setState($state) { $this->_state = $state;}
} class Caretaker { // 负责人(Caretaker)角色
private $_memento;
public function getMemento() { return $this->_memento; }
public function setMemento(Memento $memento) { $this->_memento = $memento; }
} class Client { public static function test(){ $org = new Originator();
$org->setState('open');
$org->showState(); /* 创建备忘 */
$memento = $org->createMemento(); /* 通过Caretaker保存此备忘 */
$caretaker = new Caretaker();
$caretaker->setMemento($memento); /* 改变目标对象的状态 */
$org->setState('close');
$org->showState(); /* 还原操作 */
$org->restoreMemento($caretaker->getMemento());
$org->showState(); } } Client::test(); return; try { $db->beginTransaction(); $succ = $db->exec($sql_1);
if (!$succ) {
throw new Exception('SQL 1 update failed');
} $succ = $db->exec($sql_2);
if (!$succ) {
throw new Exception('SQL 2 update failed');
} $succ = $db->exec($sql_3);
if (!$succ) {
throw new Exception('SQL 3 update failed');
} $db->commit(); } catch (Exception $exp) { $db->rollBack(); }

  

  • 深度模式

1、解释器模式(Interpreter):

定义语言的文法,并建立一个解释器解释该语言中的句子。每个用过字典的童鞋都懂滴。

好处:可扩展性比较好,灵活性大。

弊端:可能难以维护复杂的文法。

应用场景:用于成对或者一对多的需求中。

2、访问者模式(Visitor):

封装某些用于作用于某种数据结构中各元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的新操作。如银行排号机。

好处:将相关的事物集中到一个访问者对象中。

弊端:增加新数据结构很困难。

应用场景:排队,排号。

三、总结

本篇介绍了行为型模式,行为模式涉及到算法和对象职责间的分配,行为类模式采用继承机制在类间分派行为,Template Method和Interpreter是类行为模式。行为对象模式使用对象复合而不是继承,一些行为

对象模式描述了一组相互对等的对象如何相互协作以完成其中任何一个对象都单独无法完成的任务,如Mediator在对象间引入一个mediator对象提供了松耦合所需的间接性;Chain of Responsibility提供了更松的耦

合,它通过一条候选对象链隐式的向一个对象发松请求,可以运行时刻决定哪些候选者参与到链中;Observer定义并保持了对象间的依赖关系;其它的行为对象模式常将行为封装封装在一个对象中,并将请求指派给

它,Strategy模式将算法封装在对象中,这样可以方面的改变和指定一个对象所使用的算法;Command模式将请求封装在对象中,这样它就可以作为参数来传递,已可以存储在历史列表中或以其它方式使用;State

模式封装一个对象的状态,使得当这个对象的状态对象变化时,该对象可改变它的行为;Visitor模式封装分布于多个类之间的行为;而Iterator模式则抽象了访问和遍历一个集合中对象的方式。

Php设计模式(三):行为型模式part2的更多相关文章

  1. Java经典23种设计模式之行为型模式(三)

    本文接着介绍11种行为型模式里的备忘录模式.观察者模式.状态模式. 一.备忘录模式 在不破坏封装性的前提下,捕获一个对象的内部状态.并在该对象之外保存这个状态.这样以后就能够将该对象恢复到原先保存的状 ...

  2. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

  3. java设计模式---三种工厂模式之间的区别

    简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式.其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性. 本文是本人对这三种模式学习后的一个小结以及对他 ...

  4. Java设计模式之行为型模式

    行为型模式共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 策略模式:策略模式的决定权在用户,系统本身提供不同 ...

  5. Java经典23结构模型的设计模式(三)------附加代理模式、适配器型号、Facade模式的差异

    本文介绍了7样的结构模型中的其余2种:轻量级.代理模式. 一.享元模式FlyWeight 享元模式比較简单且重要,在非常多场合都被用到.仅仅只是封装起来了用户看不到.其概念:运用共享内存技术最大限度的 ...

  6. Java设计模式之职责型模式总结

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6548127.html 所谓职责型模式,就是采用各种模式来分配各个类的职责. 职责型模式包括 ...

  7. java设计模式三种工厂模式简单介绍

    一.简单工厂模式 概述:简单工厂模式的创建意图就是,把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的,只用告诉工厂我想要什么就行了.而这种方法的缺点也很明显,违背了设计 ...

  8. Java经典23种设计模式之行为型模式(二)

    本文接着介绍行为型模式里的解释器模式.迭代器模式.中介者模式. 一.解释器模式Interpret 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言的中的句子. 1 ...

  9. GoF的23种设计模式之行为型模式的特点和分类(2)

    行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配. 行为型模式分为类行为模式和对象行为模式,前者采用继 ...

随机推荐

  1. DOM手术台

    CSS分类 排队: <div id="box" style="width:200px;border:1px solid red color:red;font-siz ...

  2. Oracle中REGEXP_SUBSTR及其它支持正则表达式的内置函数小结

    Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下:在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20','23'的集合. REGEXP_SUBSTR函数格 ...

  3. SharePoint使用BCS开发你第一个应用程序(三)

    SharePoint使用BCS开发你第一个应用程序(三) 创建外部内容类型.         创建外部内容类型有三种不同方式: 1. 在记事本上手写XML代码(不推荐). 2. 使用SharePoin ...

  4. memcached 实验论文

    虽然在这个年龄段谈话memcached 它可能是一个有点晚,最为cached 在应用程序中redis 在之上,下面将谈谈自己的一些看法, 这个文件是不是memcached 理论描述,只写的实验数据和结 ...

  5. 第十七章——配置SQLServer(4)——优化SQLServer实例的配置

    原文:第十七章--配置SQLServer(4)--优化SQLServer实例的配置 前言: Sp_configure 可以用于管理和优化SQLServer资源,而且绝大部分配置都可以使用SQLServ ...

  6. Html5 拖放上传图片

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...

  7. android user如何打开一个版本号root才干

    首先,你要确认你要打开adbd 的root 才干,或者让app 它有可能获得root 才干.   (1). adbd 的root 才干 我们通常debug user 当问题的版本号, 或行为user ...

  8. jquery经常使用事件(整理)

    Jquery事件 (一).事件列表. 1.blur() 当失去焦点时触发.包含鼠标点击离开和TAB键离开. 2.change() 当元素获取焦点后,值改变失去焦点事触发. 3.click() 当鼠标单 ...

  9. 【白注意】Windows XP 大胆拥抱Linux在系统中所遇到的问题

    Windows XP至4月8日本将不再是微软官方技术支持.虽然仍可以继续使用,但他们大部分的风险.可一不留神被黑客攻击.似向下,Linux这也是一个不错的选择. 或许很多文章开始教你如何迁移,您,迁移 ...

  10. 据序和中序序列或者也许为了一个二进制序列,恢复二进制和打印图像(c语言)

    首先要预购和序,以恢复它: 1.首先,我们使用的是递归的方式来完成 2.递归的最小单位:一个空的树和书的前言和第一序.该序列的第一个元素是树的第一序列根,调用这种方法 3.递归的终止条件是.当这棵树的 ...