还记得我刚毕业的第一家公司是做b2c的,当时要做一个进销存系统,相信做过的人都应该清楚。拿最简单的进销存系统为例,其可分为采购管理、销售管理、和存货管理,三个模块相互依赖,假设现在公司为一家卖电脑的经销商:
1、销售情况
销售部门要反馈销售情况,畅销就多采购,滞销就不采购。
2、库存情况
即使是畅销产品,库存都有100台了,每天才卖出去1台,也不需要采购了!
库房有货,才能销售,空手套白狼是不行的。
库房的有容积限制的,不可有无限大,所以就有了清仓处理,需要停止采购,打拆销售。
3、督促采购
在特殊情况下,比如一个企业客户一次性购买100台,库存只有80台,这时需要催促采购。
实现代码如下:
<?php class Purchase{ public function buyComputer($number){ $stock = new Stock(); $sale = new Sale(); $saleStatus = $sale->getSaleStatus(); if($saleStatus>80){ echo "采购电脑".$number."台\n"; $stock->increase($number); }else{ $buyComputer = $number/2; echo "采购电脑".$buyComputer."台\n"; $stock->increase($buyComputer); } } public function refuseBuy(){ echo "不再采购电脑\n"; } } class Stock{ private static $computer_number = 100; public function increase($number){ self::$computer_number += $number; echo "库存数量为:".self::$computer_number."\n"; } public function decrease($number){ self::$computer_number -= $number; echo "库存数量为:".self::$computer_number."\n"; } public function getStockNumber(){ return self::$computer_number; } public function clearStock(){ $purchase = new Purchase(); $sale = new Sale(); echo "库存数量为:".self::$computer_number."\n"; //要求拆价销售 $sale->offSale(); //要求采购人员停止采购 $purchase->refuseBuy(); } } class Sale{ public function sellComputer($number){ $stock = new Stock(); $purchase = new Purchase(); if($stock->getStockNumber()<$number){ $purchase->buyComputer($number); } echo "销售电脑".$number."台\n"; $stock->decrease($number); } public function getSaleStatus(){ $saleStatus = mt_rand(0,100); echo "电脑的销售情况为:".$saleStatus."\n"; return $saleStatus; } public function offSale(){ $stock = new Stock(); echo "拆价销售电脑".$stock->getStockNumber()."台\n"; } } $purchase = new Purchase(); $purchase->buyComputer(100); $sale = new Sale(); $sale->sellComputer(1); $stock = new Stock(); $stock->clearStock(); ?> 运行结果: 电脑的销售情况为:70 采购电脑50台 库存数量为:150 销售电脑1台 库存数量为:149 库存数量为:149 拆价销售电脑149台 不再采购电脑 [Finished in 0.3s]
运行结果是我们所期望的,三个不同类型的参与者完成了各自的活动。但你有没有发现这三个类是彼此关联的?在之前的博客设计模式六原则中提到的迪米特法则认为“每个类只和朋友类交流”,这个朋友类并非越多越好,朋友类越多,耦合性越大,要想修改一个就得修改一片。何况这只是最简单的进销存,如果再加入物流管理,供应商管理,资产管理等等,那程序将会像蜘蛛网般。
现有一个助人为乐的中介者作为三个模块的交流核心,每个模块之间不再相互交流,要交流都通过中介者进行。每个模块只负责自己的业务逻辑,不属于自己的则丢给中介者处理,简化了各模块之间的耦合关系。类图如下:
修改代码如下:
<?php abstract class AbstractMediator { protected $purchase = null; protected $stock = null; protected $sale = null; public function __construct() { $this->purchase = new Purchase( $this ); $this->stock = new Stock( $this ); $this->sale = new Sale( $this ); } abstract public function execute(); } class Mediator extends AbstractMediator{ public function execute() { $args = func_get_args(); if ( !is_array( $args ) || empty( $args ) ) return; $method = $args[0]; unset( $args[0] ); call_user_func_array( array( $this, $method ), $args ); } //中介者 Mediator定义多个private方法,目的是处理各个对象之间的依赖关系。 private function buyComputer( $number ) { $saleStatus = $this->sale->getSaleStatus(); if ( $saleStatus<=80 ) { $number = $number/2; } echo "采购电脑".$number."台\n"; $this->stock->increase( $number ); } private function clearStock() { echo "库存数量为:".$this->stock->getStockNumber()."\n"; //要求拆价销售 $this->sale->offSale(); //要求采购人员停止采购 $this->purchase->refuseBuy(); } private function sellComputer( $number ) { if ( $this->stock->getStockNumber()<$number ) { $this->purchase->buyComputer( $number ); } echo "销售电脑".$number."台\n"; $this->stock->decrease( $number ); } private function offSale() { echo "拆价销售电脑".$this->stock->getStockNumber()."台\n"; } } abstract class AbstractColleague { protected $mediator = null; public function __construct( $mediator ) { $this->mediator = $mediator; } } class Purchase extends AbstractColleague{ public function buyComputer( $number ) { $this->mediator->execute( 'buyComputer', $number ); } public function refuseBuy() { echo "不再采购电脑\n"; } } class Stock extends AbstractColleague{ private static $computer_number = 100; public function increase( $number ) { self::$computer_number += $number; echo "库存数量为:".self::$computer_number."\n"; } public function decrease( $number ) { self::$computer_number -= $number; echo "库存数量为:".self::$computer_number."\n"; } public function getStockNumber() { return self::$computer_number; } public function clearStock() { $this->mediator->execute( 'clearStock' ); } } class Sale extends AbstractColleague{ public function sellComputer( $number ) { $this->mediator->execute( 'sellComputer', $number ); } public function getSaleStatus() { $saleStatus = mt_rand( 0, 100 ); echo "电脑的销售情况为:".$saleStatus."\n"; return $saleStatus; } public function offSale() { $this->mediator->execute( 'offSale' ); } } $mediator = new Mediator(); $purchase = new Purchase( $mediator ); $purchase->buyComputer( 100 ); $sale = new Sale( $mediator ); $sale->sellComputer( 1 ); $stock = new Stock( $mediator ); $stock->clearStock(); ?> 运行结果: 电脑的销售情况为:70 采购电脑50台 库存数量为:150 销售电脑1台 库存数量为:149 库存数量为:149 拆价销售电脑149台 不再采购电脑 [Finished in 0.3s]
加入中介者后,设计结构清晰了很多,而且类间的耦合性大大减少,代码质量也有了很大的提升。
中介者模式的定义
用一个中介对象封装一系列的对象交互,中介者使各对象不需要显性地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
中介者模式由以下几部门组成:
1、Mediator 抽象中介者角色
抽象中介者角色定义统一的接口,用于各同事角色之间的通信。
2、 Concrete Mediator 具体中介者角色
具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。
3、Colleague 同事角色
每一个同事角色都知道中介者角色,并且与其他的同事角色通信的时候,一定要通过中介者角色协作。每个同事类的行为分为两种:一种是同事本身的行为,比如改变对象本身的状态,处理自己的行为等,这种行为叫做自发行为(Self-Method),与其他的同事类或中介者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。
中介者模式的优点
减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合
中介者模式的缺点
中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑也就越复杂。
中介者模式的实际应用(MVC)
相信大家都使用过MVC框架,其中的C(controller)就是一个中介者,叫做前端控制器(Front Controller),它的作用就是把M和V隔离开,协调M和V协同工作,把M运行的结果和V代表的视图融合成一个前端可以展示的页面,减少M和V的依赖关系。
中介者模式是一个非常好的封装模式,也是一个很容易被滥用的模式,一个对象依赖几个对象是再正常不过的事情,但是纯理论家就会要求使用中介者模式来封装这种依赖关系,这是非常危险的!因此在使用时请考虑中介者带来的膨胀问题。
相关推荐
中介者模式(Mediator Pattern)是一种行为型设计模式,用于减少对象之间的直接相互依赖,使得对象间的交互通过一个中介者对象来进行协调。在中介者模式中,对象之间不再直接相互调用,而是通过中介者对象来传递消息...
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
中介者模式(Mediator) 用意:用一个中介对象来封装一系列对象间的交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
咱们先来看下中介者模式(Mediator Pattern)的定义,它就是,用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互,这种模式又称为调停...
C#面向对象设计模式 (行为型模式) Mediator 中介者模式 视频讲座下载
主要介绍了Java设计模式之中介者模式(Mediator Pattern),需要的朋友可以参考下
主要介绍了javascript设计模式之中介者模式Mediator,需要的朋友可以参考下
中介者模式的完整代码。 程序默认使用vs开发。其他开发工具可能需要做少许调整。
C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式
提供者模式(Provider Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 原型模式(Prototype Pattern) 责任链模式(Chain of Responsibility Pattern) 中介者模式(Mediator Pattern) 装饰模式...
NULL 博文链接:https://hnzhoujunmei.iteye.com/blog/1033405
Mediator 中介者模式 若有问题,烦请指出。
php /** * 中介者模式 * * 用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用从而使其耦合松散,而且可以独立地改变它们之间的交互 */ abstract class Mediator { abstract public function send($...
中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式...
中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者模式(Visitor Pattern) 23. 状态模式(State Pattern)
C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式 (Level 300)
中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者模式(Visitor Pattern) 23. 状态模式...
中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 策略模式(Strategy Pattern) 模板方法模式(Template Method ...