JAVA设计模式之中介者模式

1. 什么是中介者模式?

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


如果系统之中出现大量对象之间相互引用,将会造成

(1)系统结构变得复杂。对象与对象之间存在大量相互引用,若一个对象改变,与之关联的对象都可能要做出相应的改变。

(2)系统可扩展性降低。增加一个对象,就要去其他相关对象上面增加此对象的引用。增加了对象之间的耦合性。

(3)对象复用性降低。一个对象存在很多其他对象的引用,导致此对象不易于复用于其他场景。

 

图片源于网络

 

图中A对象中就有BCDHG对象的引用,A对象和这几个对象是直接耦合的,不易于扩展与维护。采用中介者模式后,所有对象都只和中介者(Mediator)打交道,所有的调用关系都是中介者来维护的。此时此刻A对象解脱了,假如A有份报告要交给BCD,他不用自己亲自给每个对象送去了,只需要交给Mediator转发给BCD就可以了。


但是一定要注意,因为中介者中维护了几乎所有对象的引用和调用行为,中介者会变得异常复杂和庞大。所以遇到大量对象相互引用的时候一定要权衡利弊,设计是否合理,不是说只要使用模式一定就是最好的。

2. 角色

 

图片源于网络

抽象中介者(Mediator):中介者抽象类。提供了一个同事对象联络的抽象方法。可以是接口或抽象类。


具体中介者(ConcreteMediator):实现抽象中介者类的抽象方法。具体中介者需要知道所有具体同事类,并且将一个具体同事类的信息传递给另一个具体同事类。


抽象同事(Colleague):定义所有具体同事的共同方法。可以是接口或抽象类。


具体同事(ConcreteColleague):实现抽象同事类的抽象方法。内部有一个中介者的引用。


3. 优点

(1)将系统对象与对象直接的调用关系分离出来进行单独封装,同事对象(Colleague)内没有显式的的调用其他同事对象,使耦合松散。

(2)同事对象(Colleague)抽离了对其他对象的引用,使得同事对象可以重用于不同的场景,不用单独扩展,可以使同事对象的数量减少。

4. 缺点

当使用中介者模式将对象与对象之间的调用关系分离出来后,中介者内部必须要知道每一个对象类和他们之间的调用关系,这会造成中介者代码复杂且庞大,很不容易维护。


如果有4个同事对象需要相互联系,则中介者对象中就会存在4*3=12种不同的相互调用方法,同事对象越多,中介者越复杂庞大。因此个人觉得,如果将接收者和发送者交给客户端来注册,不完全交给中间者管理,中介者对象只需要维护已经注册了的发送者和接收者,以及他们之间相互调用的公共方法,中介者会相对较好维护。如6例。

5. 使用场景

(1)系统对象之间存在复杂的引用关系,系统结构混乱难以理解。

(2)一个对象直接引用了其他对象,且直接和他们进行通信,造成这个对象难以复用与其他场景。

(3)想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。


个人理解:其实这个就是造成中介者代码复杂庞大的原因,因为为了不生成太多的子类,中介者就需要维护所有的交互行为,4个对象就有12种交互行为,6个对象就有30种交互行为,因此示例代码中所举例子,采用一种折中的办法,中介者不维护所有的交互关系和交互对象,只维护抽象发送者、抽象接收者和公共调用关系,而实际的发送者和接收者交给客户端进行注册。

6. 示例代码

每种事物都具有两面性,此例子虽然解决了中介者类复杂庞大不好维护的缺点,但是却不能实现接收者与接收者对话,如B、C、D之间的对话。想要B、C、D之间相互对话必须重新注册接收者和发送者。

(1)抽象中介者

/**
 * 抽象中介者类
 */
public interface IMediator {
	/**
	 * 中介者给同事双方相互联系的方法
	* @param person   发送请求的同事类
	* @param message  发送的消息
	 */
	public void contact(String message,AbstractPerson person);
}

(2)具体中介者

/**
 * 具体的中介者对象
 */
public class ConcreteMediator implements IMediator {
	// 接收者(list列表可以实现一个发送者和多个接收者对话,一对多关系)
	private List<AbstractPerson> receivers = new ArrayList<AbstractPerson>();
	// 发送者
	private AbstractPerson sender;

	/**
	 * 注册接收者
	 * @param persons
	 */
	public void setReceiver(AbstractPerson... persons) {
		if (persons != null && persons.length > 0)
			for (AbstractPerson person : persons) {
				receivers.add(person);
			}
	}

	/**
	 * 删除接收者
	 * @param receiver
	 */
	public void removeReceiver(AbstractPerson...RECEIVERS) {
		if (RECEIVERS != null && RECEIVERS.length > 0)
			for(AbstractPerson receiver:RECEIVERS)
				receivers.remove(receiver);
	}

	/**
	 * 注册发送者
	 * @param persen
	 */
	public void setSender(AbstractPerson persen) {
		this.sender = persen;
	}

	@Override
	public void contact(String message, AbstractPerson person) {
		if (person == sender) {
			for (AbstractPerson receiver : receivers)
				receiver.handleMessage(message);
		} else {
			sender.handleMessage(message);
		}
	}
}


(3)抽象同事

/**
 *公共抽象同事类
 *由于有重复的属性和方法,此处采用abstract类
 */
public abstract class AbstractPerson {

	protected IMediator mediator;
	protected String personName;
	public AbstractPerson(String personName,IMediator mediator) {
		this.personName=personName;
		this.mediator=mediator;
	}
	/**
	 * 同事之间联系的方法
	* @param message  发送的消息
	 */
	public void contact(String message){
		if(message!=null && !"".equals(message))
			mediator.contact(message,this);
	}
	
	/**
	 * 此对象处理消息的方法
	* @param message  接收到的消息
	 */
	public abstract void handleMessage(String message);

}

(4)具体同事

/**
 * 具体同事A
 */
public class PersonA extends AbstractPerson {

	public PersonA(String personName,IMediator mediator) {
		super(personName, mediator);
	}

	@Override
	public void handleMessage(String message) {
		if(message!=null && !"".equals(message))
			System.out.println(personName+" 收到消息:"+message);
	}
}

/**
 * 具体同事B
 */
public class PersonB extends AbstractPerson{

	public PersonB(String personName,IMediator mediator) {
		super(personName, mediator);
	}

	@Override
	public void handleMessage(String message) {
		if(message!=null && !"".equals(message))
			System.out.println(personName+" 收到消息:"+message);
	}
}

/**
 * 具体同事C
 */
public class PersonC extends AbstractPerson {

	public PersonC(String personName,IMediator mediator) {
		super(personName, mediator);
	}

	@Override
	public void handleMessage(String message) {
		if(message!=null && !"".equals(message))
			System.out.println(personName+" 收到消息:"+message);
	}
}

/**
 * 具体同事D
 */
public class PersonD extends AbstractPerson {

	public PersonD(String personName,IMediator mediator) {
		super(personName, mediator);
	}

	@Override
	public void handleMessage(String message) {
		if(message!=null && !"".equals(message))
			System.out.println(personName+" 收到消息:"+message);
	}
}

 

(5)测试

public class Client {

	public static void main(String[] args) {
		//new一个中介者
		ConcreteMediator mediator=new ConcreteMediator();
		//new一个发送者A
		AbstractPerson personA=new PersonA("A君", mediator);
		//new一个接收者B
		AbstractPerson personB=new PersonB("B君", mediator);
		//注册发送者
		mediator.setSender(personA);
		//注册接收者
		mediator.setReceiver(personB);
		System.out.println("A对B说:");
		personA.contact("B君,你吃早饭没有?");
		System.out.println("-----------");
		
		//再new 多个接收者
		AbstractPerson personC=new PersonC("C君", mediator);
		AbstractPerson personD=new PersonD("D君", mediator);
		mediator.setReceiver(personC,personD);
		
		System.out.println("A对BCD说:");
		personA.contact("你们今天编程了吗?");
		System.out.println("-----------");
		
		System.out.println("DBC分别回答A:");
		personD.contact("A君,别装逼!");
		personB.contact("呵呵");
		personC.contact("今天天气不错!");
		System.out.println("-----------");
		
		//清除B和C接收者
		mediator.removeReceiver(personB,personC);
		System.out.println("A单独对D说:");
		personA.contact("D君,别BB!");
		
	}
}

(6)测试结果

A对B说:
B君 收到消息:B君,你吃早饭没有?
-----------
A对BCD说:
B君 收到消息:你们今天编程了吗?
C君 收到消息:你们今天编程了吗?
D君 收到消息:你们今天编程了吗?
-----------
DBC分别回答A:
A君 收到消息:A君,别装逼!
A君 收到消息:呵呵
A君 收到消息:今天天气不错!
-----------
A单独对D说:
D君 收到消息:D君,别BB!

注意:文中自我理解部分属于自己的对中介者模式的一种理解,不能说全对,若不对请批评指正!

【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】

参考文章http://www.cnblogs.com/chenssy/p/3348520.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值