23个java设计模式(九)-- 中介者模式

2016年03月18日 原创
关键词: java 设计模式
摘要 中介者模式用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。

一、概述。

中介者模式用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。

一个对象含有另一个对象的引用正是面向对象中经常使用的方式,也是面向对象所提倡的,即少用继承多用组合。但是怎样合理地组合对象对系统今后的扩展、维护和对象的复用是至关重要的,这也是学习设计模式的重要原因。对于某些特殊系统,特别是涉及很多对象时,该系统可能不希望对象之间直接交互,即不希望这些对象之间互相包含对方的引用,其原因是不利于系统今后的扩展、维护以及对象的复用。

中介者使系统中的其他对象完全解耦,当系统中某个对象需要和系统中另外一个对象交互时,只需将自己的请求通知中介者即可,如果有新的加入者,该加入者只需含有中介者的引用,并让中介者含有自己的引用,他就可以和系统中其他对象进行相关操作。

二、中介者模式的结构。

中介者模式的结构中包括四种角色:

  • 中介者(Mediator):中介者使一个接口,该接口定义了用于同事(Colleague)对象之间进行通信的方法。
  • 具体中介者(ConcreteMediator):具体中介者是实现中介者接口的类。具体中介者需要包含所有具体同事(ConcreteColleague)的引用,并通过实现中介者接口中的方法来满足具体同事之间的通信请求。
  • 同事(Colleague):一个接口,规定了具体同事需要实现的方法。
  • 具体同事(ConcreteColleague):实现同事接口的类。具体同事需要包含具体中介者的引用,一个具体同事需要和其他具体同事交互时,只需将自己的请求通知给它所包含的具体中介者即可。

三、示例程序。

同事

public interface Colleague {
	public void giveMsg(String[] msg);
	public void receiveMsg(String msg);
	public void setName(String name);
	public String getName();
}

具体中介者

public class ConcreteMediator {
	private ColleagueA colleagueA;
	private ColleagueB colleagueB;
	private ColleagueC colleagueC;
	public void registerColleagueA(ColleagueA colleagueA) {
		this.colleagueA = colleagueA;
	}
	public void registerColleagueB(ColleagueB colleagueB) {
		this.colleagueB = colleagueB;
	}
	public void registerColleagueC(ColleagueC colleagueC) {
		this.colleagueC = colleagueC;
	}
	
	public void deliverMsg(Colleague colleague, String[] msg) {
		if(colleague==colleagueA) {
			if(msg.length>=2) {
				colleagueB.receiveMsg(colleague.getName()+msg[0]);
				colleagueC.receiveMsg(colleague.getName()+msg[1]);
			}
		}
		else if(colleague==colleagueB) {
			if(msg.length>=2) {
				colleagueA.receiveMsg(colleague.getName()+msg[0]);
				colleagueC.receiveMsg(colleague.getName()+msg[1]);
			}
		}
		else {
			if(msg.length>=2) {
				colleagueA.receiveMsg(colleague.getName()+msg[0]);
				colleagueB.receiveMsg(colleague.getName()+msg[1]);
			}
		}
	}
}

具体同事

public class ColleagueA implements Colleague{
	private ConcreteMediator mediator;
	private String name;
	
	public ColleagueA(ConcreteMediator mediator) {
		this.mediator = mediator;
		mediator.registerColleagueA(this);
	}
	
	@Override
	public void giveMsg(String[] msg) {
		mediator.deliverMsg(this, msg);
	}

	@Override
	public void receiveMsg(String msg) {
		System.out.println(name+"收到的信息:");
		System.out.println("\t"+msg);
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return this.name;
	}
	
}


public class ColleagueB implements Colleague{
	private String name;
	private ConcreteMediator mediator;
	
	public ColleagueB(ConcreteMediator mediator) {
		this.mediator = mediator;
		mediator.registerColleagueB(this);
	}

	@Override
	public void giveMsg(String[] msg) {
		mediator.deliverMsg(this, msg);
	}

	@Override
	public void receiveMsg(String msg) {
		System.out.println(name+"收到的信息:");
		System.out.println("\t"+msg);
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return this.name;
	}
	
}


public class ColleagueC implements Colleague{
	private String name;
	private ConcreteMediator mediator;
	
	public ColleagueC(ConcreteMediator mediator) {
		this.mediator = mediator;
		mediator.registerColleagueC(this);
	}

	@Override
	public void giveMsg(String[] msg) {
		mediator.deliverMsg(this, msg);
	}

	@Override
	public void receiveMsg(String msg) {
		System.out.println(name+"收到的信息:");
		System.out.println("\t"+msg);
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return this.name;
	}

}

测试程序

public class Example1Test {
	@Test
	public void testMain() {
		ConcreteMediator mediator = new ConcreteMediator();
		ColleagueA colleagueA = new ColleagueA(mediator);
		ColleagueB colleagueB = new ColleagueB(mediator);
		ColleagueC colleagueC = new ColleagueC(mediator);
		colleagueA.setName("A国");
		colleagueB.setName("B国");
		colleagueC.setName("C国");
		String[] msgA = {"要求归还曾抢夺的100斤土豆","要求归还曾抢夺的20头牛"};
		String[] msgB = {"要求归还曾抢夺的10只公鸡","要求归还曾抢夺的15匹马"};
		String[] msgC = {"要求归还曾抢夺的300斤小麦","要求归还曾抢夺的50头驴"};
		colleagueA.giveMsg(msgA);
		colleagueB.giveMsg(msgB);
		colleagueC.giveMsg(msgC);
	}
}

四、中介者模式的优点。

  1. 可以避免许多的对象为了之间的通信而相互显式引用,否则,不仅系统难于维护,而且也使其他系统难以复用这些对象。
  2. 可以通过中介者将原本分布于多个对象之间的交互行为集中在一起。当这些对象之间需要改变之间的通信行为时,只需使用一个具体中介者即可,不必修改各个具体同事的代码,即这些同事可被重用。
  3. 具体中介者使得各个具体同事完全解耦,修改任何一个具体同事的代码不会影响到其他同事。
  4. 具体中介者集中了同事之间是如何交互的细节,使系统比较清楚地知道整个系统中的同事是如何交互的。
  5. 当一些对象想互相通信,但又无法相互包含对方的引用,那么使用中介者模式就可以使这些对象互相通信。

注:由于具体中介者集中了同事之间是如何交互的细节,可能使具体中介者变得非常复杂,增加了维护的难度。

五、适合使用中介者模式的情景。

  1. 许多对象以复杂的方式交互,所导致的依赖关系使系统难以理解和维护。
  2. 一个对象引用其他很多对象,导致难以复用该对象。