PHP设计模式之中介者模式(Mediator Pattern)了解下

咱们先来看下中介者模式(Mediator Pattern)的定义,它就是,用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互,这种模式又称为调停者模式,它是一种对象行为型模式。

我们先来看用户与用户直接聊天的设计方案。

在这个方案设计的过程中,我们可以发挥想象,用户对象之间存在很强的关联性,将导致系统出现如下问题:

  1. 系统结构复杂:对象之间存在大量的相互关联和调用,若有一个对象发生变化,则需要跟踪和该对象关联的其他所有对象,并进行适当处理
  2. 对象可重用性差:由于一个对象和其他对象具有很强的关联,若没有其他对象的支持,一个对象很难被另一个系统或模块重用,这些对象表现出来更像一个不可分割的整体,职责较为混乱
  3. 系统扩展性低:增加一个新的对象需要在原有相关对象上增加引用,增加新的引用关系也需要调整原有对象,系统耦合度很高,对象操作很不灵活,扩展性差 

然而,在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,但是,对于一个模块来说,可能由很多对象构成,而且这些对象之间可能存在相互的引用,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式,这就是我们使用中介者模式的动机。

来看下中介者模式包含的角色:

  Mediator: 抽象中介者,在里面定义了各个同事之间相互交互所需要的方法。
  ConcreteMediator: 具体中介者,它需要了解并为维护每个同事对象,并负责具体的协调各个同事对象的交互关系。
  Colleague:抽象同事类,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能
  ConcreteColleague:具体同事类,实现自己的业务,需要与其他同事对象交互,就通知中介对象,中介对象会负责后续的交互

再来看下图片感受下:

来看一个完整的实例:

  1. 我们有一个CD类和一个MP3类,两个类的结构相似。
  2. 我们需要在CD类更新的时候,同步更新MP3类。
  3. 传统的做法就是在CD类中实例化MP3类,然后去更新,但是这么做的话,代码就会很难维护,如果新增一个同样的MP4类,那么就没法处理了。
  4. 中介者模式很好的处理了这种情况,通过中介者类,CD类中只要调用中介者这个类,就能同步更新这些数据。

代码实例如下:

<?php
class CD {
	public $band  = '';           
	public $title = '';           
	protected $_mediator;  
	
	public function __construct(MusicContainerMediator $mediator = NULL) {               
		$this->_mediator = $mediator;           
	}
	
	public function save() {              
		//具体实现待定               
		var_dump($this);           
	}
	
	public function changeBandName($bandname) {               
		if ( ! is_null($this->_mediator)) {                   
			$this->_mediator->change($this, array("band" => $bandname));               
		}               
		$this->band = $bandname;               
		$this->save();           
	}         
}
//MP3Archive类       
class MP3Archive {                      
	protected $_mediator;                      
	
	public function __construct(MusicContainerMediator $mediator = NULL) {               
		$this->_mediator = $mediator;           
	}                      
	
	public function save() {               
		//具体实现待定             
		var_dump($this);           
	}                      
	
	public function changeBandName($bandname) {               
		if ( ! is_null($this->_mediator)) {                   
			$this->_mediator->change($this, array("band" => $bandname));               
		}               
		$this->band = $bandname;               
		$this->save();           
	}       
	
}   
 
 //中介者类       
class MusicContainerMediator {                      
	protected $_containers = array();                      
	
	public function __construct() {               
		$this->_containers[] = "CD";               
		$this->_containers[] = "MP3Archive";           
	}                      
	
	public function change($originalObject, $newValue) {               
		$title = $originalObject->title;               
		$band  = $originalObject->band;                              
		foreach ($this->_containers as $container) {                   
			if ( ! ($originalObject instanceof $container)) {                      
				$object = new $container;                       
				$object->title = $title;                       
				$object->band  = $band;                                              
				foreach ($newValue as $key => $val) {                
					$object->$key = $val;                       
				}                                              
				$object->save();                   
			}               
		}           
	}       
}   
 
//测试实例       
$titleFromDB = "Waste of a Rib";       
$bandFromDB  = "Never Again";       
$mediator = new MusicContainerMediator();       
$cd = new CD($mediator);       
$cd->title = $titleFromDB;       
$cd->band  = $bandFromDB;       
$cd->changeBandName("Maybe Once More");  

还有个实例,一起看下吧:

//抽象同事类,家教
abstract class Tutor{
    protected $message;   //个人信息
    protected $mediator;  //为家教服务的中介机构
    function __construct($message,Mediator $mediator){
        $this->message = $message;
        $this->mediator = $mediator;
    }
    //获取个人信息
    function getMessage(){
        return $this->message;
    }
    //找学生
    abstract function findStudent();
}
//具体同事类,大学生家教
class UndergraduateTutor extends Tutor{
   //家教类型
   public $type = "UndergraduateTutor";

   function __construct($message,Mediator $mediator){
          parent::__construct($message,$mediator);
   }
   //找学生,让中介机构代为寻找
   function findStudent(){
         $this->mediator->matchStudent($this);
   }
}
//具体同事类,高中生家教
class SeniorStudentTutor extends Tutor{
    //家教类型
   public $type = "SeniorStudentTutor";
   
   function __construct($message,Mediator $mediator){
          parent::__construct($message,$mediator);
   }
   //找学生,让中介机构代为寻找
   function findStudent(){
         $this->mediator->matchStudent($this);
   }
}
//具体同事类,初中生家教
class MiddleStudentTutor extends Tutor{
    //家教类型
   public $type = "MiddleStudentTutor";
   
   function __construct($message,Mediator $mediator){
          parent::__construct($message,$mediator);
   }
   //找学生,让中介机构代为寻找
   function findStudent(){
         $this->mediator->matchStudent($this);
   }
}

//抽象中介类
abstract class AbstractMediator{
    abstract function matchStudent(Tutor $tutor);
}
//具体中介类,为家教匹配合适的学生
class Mediator extends AbstractMediator{
    //定义其服务的所有家教,不在范围内的不服务
    private $serveObject = array("UndergraduateTutor","SeniorStudentTutor","MiddleStudentTutor");
    //匹配学生  
    function matchStudent(Tutor $tutor){
         for($i=0;$i<count($this->serveObject);$i++){
              if($tutor->type == $this->serveObject[$i]){
                  $message = $tutor->getMessage();
                  echo "该家教个人信息为".print_r($message)."<br/>将为其匹配合适的学生";
                  break;
              }
         }
         if($i>=count($this->serveObject)){
             echo "该家教不在我中介机构服务范围内";
         }
    }
}

//测试
$mediator = new Mediator();
$undergraduateTutor = new UndergraduateTutor(array("name"=>"张三","age"=>22),$mediator);
$undergraduateTutor->findStudent();
//结果:该家教个人信息为 Array ( [name] => 张三 [age] => 22 ),将为其匹配合适的学生

好啦,本次记录就到这里了。

如果感觉不错的话,请多多点赞支持哦。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值