Php设计模式(三):行为型模式part2
<接上一篇>
10年积累的网站设计制作、做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站制作后付款的网站建设流程,更有大关免费网站建设让你可以放心的选择与我们合作。
5、中介者模式(Mediator):
用中介对象封装一系列的对象交互,中介使各对象不需要显式地相互引用。类似于邮局,邮寄者和收件者不用自己跑很远路,通过邮局就可以。
好处:简化了对象之间的关系,减少子类的生成
弊端:中介对象可能变得非常复杂,系统难以维护
应用场景:不需要显示地建立交互
代码实现:
_mediator = $mediator; } publicfunction send($message) { $this->_mediator->send($message,$this); } abstractpublic function notify($message); } class ConcreteMediator extends Mediator { // 具体中介者角色 private$_colleague1 = null; private$_colleague2 = null; publicfunction send($message,$colleague) { if($colleague == $this->_colleague1) { $this->_colleague1->notify($message); } else{ $this->_colleague2->notify($message); } } publicfunction set($colleague1,$colleague2) { $this->_colleague1 = $colleague1; $this->_colleague2 = $colleague2; } } class Colleague1 extends Colleague { // 具体对象角色 publicfunction notify($message) { output(sprintf('Colleague-1: %s', $message)); } } class Colleague2 extends Colleague { // 具体对象角色 publicfunction notify($message) { output(sprintf('Colleague-2: %s', $message)); } } class Client { publicstatic 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语句实用,方便增加新状态,封装了状态转换规则。
弊端:增加系统类和对象的数量。
应用场景:用于对象的不同功能的转换。
代码实现:
state = $state; } //电梯门关闭 publicfunction 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'); } //电梯门开启 publicfunction 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'); } ///电梯开始跑起来 publicfunction 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'); } //电梯停止 publicfunction 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 { publicstatic function test() { $lift= new Lift(); //电梯的初始条件应该是停止状态 $lift->setState(ILift::STOPPING_STATE); //首先是电梯门开启,人进去 $lift->open(); //然后电梯门关闭 $lift->close(); //再然后,电梯跑起来,向上或者向下 $lift->run(); //最后到达目的地,电梯挺下来 $lift->stop(); } } Client::test();
_context = $context; } //首先电梯门开启动作 publicabstract function open(); //电梯门有开启,那当然也就有关闭了 publicabstract function close(); //电梯要能上能下,跑起来 publicabstract function run(); //电梯还要能停下来,停不下来那就扯淡了 publicabstract function stop(); } /** * 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。 */ class Context { //定义出所有的电梯状态 static $openningState =null; static $closeingState =null; static $runningState = null; static $stoppingState =null; publicfunction __construct() { self::$openningState = new OpenningState(); self::$closeingState = new ClosingState(); self::$runningState = new RunningState(); self::$stoppingState = new StoppingState(); } //定一个当前电梯状态 private $_liftState; publicfunction getLiftState() { return$this->_liftState; } publicfunction setLiftState($liftState) { $this->_liftState = $liftState; //把当前的环境通知到各个实现类中 $this->_liftState->setContext($this); } publicfunction open(){ $this->_liftState->open(); } publicfunction close(){ $this->_liftState->close(); } publicfunction run(){ $this->_liftState->run(); } publicfunction stop(){ $this->_liftState->stop(); } } /** * 在电梯门开启的状态下能做什么事情 */ class OpenningState extends LiftState { /** * 开启当然可以关闭了,我就想测试一下电梯门开关功能 * */ publicfunction close() { //状态修改 $this->_context->setLiftState(Context::$closeingState); //动作委托为CloseState来执行 $this->_context->getLiftState()->close(); } //打开电梯门 publicfunction open() { output('lift open...'); } //门开着电梯就想跑,这电梯,吓死你! publicfunction run() { //donothing; } //开门还不停止? publicfunction stop() { //donothing; } } /** * 电梯门关闭以后,电梯可以做哪些事情 */ class ClosingState extends LiftState { //电梯门关闭,这是关闭状态要实现的动作 publicfunction close() { output('lift close...'); } //电梯门关了再打开,逗你玩呢,那这个允许呀 publicfunction open() { $this->_context->setLiftState(Context::$openningState); //置为门敞状态 $this->_context->getLiftState()->open(); } //电梯门关了就跑,这是再正常不过了 publicfunction run() { $this->_context->setLiftState(Context::$runningState); //设置为运行状态; $this->_context->getLiftState()->run(); } //电梯门关着,我就不按楼层 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //设置为停止状态; $this->_context->getLiftState()->stop(); } } /** * 电梯在运行状态下能做哪些动作 */ class RunningState extends LiftState { //电梯门关闭?这是肯定了 publicfunction close() { //donothing } //运行的时候开电梯门?你疯了!电梯不会给你开的 publicfunction open() { //donothing } //这是在运行状态下要实现的方法 publicfunction run() { output('lift run...'); } //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //环境设置为停止状态; $this->_context->getLiftState()->stop(); } } /** * 在停止状态下能做什么事情 */ class StoppingState extends LiftState { //停止状态关门?电梯门本来就是关着的! publicfunction close() { //donothing; } //停止状态,开门,那是要的! publicfunction open() { $this->_context->setLiftState(Context::$openningState); $this->_context->getLiftState()->open(); } //停止状态再跑起来,正常的很 publicfunction run() { $this->_context->setLiftState(Context::$runningState); $this->_context->getLiftState()->run(); } //停止状态是怎么发生的呢?当然是停止方法执行了 publicfunction stop() { output('lift stop...'); } } /** * 模拟电梯的动作 */ class Client { publicstatic function test() { $context = new Context(); $context->setLiftState(new ClosingState()); $context->open(); $context->close(); $context->run(); $context->stop(); } } Client::test();
7、职责链模式 (Chainof Responsibility):
多个对象有机会处理请求,为请求发送者和接收者解耦。就像银行里的取款机,不管那一台都可以取到钱。
好处:简单化对象隐藏链结构,便于添加新职责节点
弊端:请求可能没有接受者,或者被多个接收者调用,性能降低
应用场景:处理多种请求
代码实现:
_handler = $handler; } protected function_success($request) { output(sprintf("%s's request was passed",$request->getName())); returntrue; } abstractfunction handleRequest($request); } /** * 具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。 * */ class ConcreteHandlerLeader extends Handler { function__construct($handlerName){ $this->_handlerName = $handlerName; } publicfunction 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; } publicfunction 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 extendsHandler { function__construct($handlerName){ $this->_handlerName = $handlerName; } publicfunction 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; } publicfunction setName($name){ $this->_name = $name; } publicfunction getName(){ return $this->_name; } publicfunction setDay($day){ $this->_day = $day; } publicfunction getDay(){ return $this->_day ; } publicfunction setReason($reason ){ $this->_reason = $reason; } publicfunction getReason( ){ return $this->_reason; } } class Client { publicstatic function test(){ $leader= new ConcreteHandlerLeader('leader'); $manager = new ConcreteHandlerManager('manager'); $generalManager = newConcreteHandlerGeneralManager('generalManager'); //请求实例 $request = new Request('ucai',4,'休息'); $leader->setSuccessor($manager); $manager->setSuccessor($generalManager); $result = $leader->handleRequest($request); } } Client::test();
8、策略模式(Strategy):
定义一系列算法,把每一个算法封装起来,并且使它们可相互替换。就像篮球队里的球员,场上的和场下休息的。教练可以让场上的下来,也可以让场下的上阵。
好处:定义可重用的一系列算法和行为,并且消除了if else语句
弊端:调用端必须知道所有策略类
应用场景:用于对象间的替换
代码实现:
OnTheWay(); } } class Client { publicstatic function test(){ $travel = new Context(); $travel->find(new WalkStrategy()); $travel->find(new RideBickStrategy()); $travel->find(new CarStrategy()); } } Client::test();
已知模式
1、备忘录模式(Memento):
保存对象在一时刻的状态。亲,还记得“老师来了记得叫我一下”的同桌的他吗?
好处:给用户提供了一种可以恢复状态的机制
弊端:消耗资源
应用场景:用于需要保存的数据
代码实现:
_state = ''; } publicfunction createMemento() { // 创建备忘录 returnnew Memento($this->_state); } publicfunction restoreMemento(Memento $memento) { // 将发起人恢复到备忘录对象记录的状态上 $this->_state = $memento->getState(); } publicfunction setState($state) { $this->_state = $state; } publicfunction getState() { return $this->_state; } publicfunction showState() { output($this->_state); } } class Memento { // 备忘录(Memento)角色 private$_state; publicfunction __construct($state) { $this->setState($state); } publicfunction getState() { return $this->_state; } publicfunction setState($state) { $this->_state = $state;} } class Caretaker { // 负责人(Caretaker)角色 private$_memento; public functiongetMemento() { return $this->_memento; } publicfunction setMemento(Memento $memento) { $this->_memento = $memento; } } class Client { publicstatic 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) { thrownew Exception('SQL 1 update failed'); } $succ = $db->exec($sql_2); if(!$succ) { thrownew Exception('SQL 2 update failed'); } $succ = $db->exec($sql_3); if(!$succ) { throw newException('SQL 3 update failed'); } $db->commit(); } catch (Exception $exp) { $db->rollBack(); }
深度模式
1、解释器模式(Interpreter):
定义语言的文法,并建立一个解释器解释该语言中的句子。每个用过字典的童鞋都懂滴。
好处:可扩展性比较好,灵活性大
弊端:可能难以维护复杂的文法
应用场景:用于成对或者一对多的需求中
2、访问者模式(Visitor):
封装某些用于作用于某种数据结构中各元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的新操作。如银行排号机。
好处:将相关的事物集中到一个访问者对象中。
弊端:增加新数据结构很困难
应用场景:排队,排号
三、总结
本篇介绍了行为型模式,行为模式涉及到算法和对象职责间的分配,行为类模式采用继承机制在类间分派行为,TemplateMethod和Interpreter是类行为模式。行为对象模式使用对象复合而不是继承,一些行为对象模式描述了一组相互对等的对象如何相互协作以完成其中任何一个对象都单独无法完成的任务,如Mediator在对象间引入一个mediator对象提供了松耦合所需的间接性;Chain of Responsibility提供了更松的耦合,它通过一条候选对象链隐式的向一个对象发松请求,可以运行时刻决定哪些候选者参与到链中;Observer定义并保持了对象间的依赖关系;其它的行为对象模式常将行为封装封装在一个对象中,并将请求指派给它,Strategy模式将算法封装在对象中,这样可以方面的改变和指定一个对象所使用的算法;Command模式将请求封装在对象中,这样它就可以作为参数来传递,已可以存储在历史列表中或以其它方式使用;State模式封装一个对象的状态,使得当这个对象的状态对象变化时,该对象可改变它的行为;Visitor模式封装分布于多个类之间的行为;而Iterator模式则抽象了访问和遍历一个集合中对象的方式。
当前文章:Php设计模式(三):行为型模式part2
网站链接:http://scjbc.cn/article/gigdcj.html