设计模式--14中介者模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式--14中介者模式相关的知识,希望对你有一定的参考价值。

定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。

类型:行为类模式

看看结构图的形象描述吧:

技术分享

中介者模式的结构

       中介者模式又称为调停者模式,从类图中看,共分为3部分:

  •  抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
  • 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
  • 同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。

为什么要使用中介者模式

       一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。

技术分享技术分享

        如果引入中介者模式,那么同事类之间的关系将变为星型结构,从图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。

技术分享

对于设计模式这个东西,理解了,应该写一个代码体会一下,我们以qq和email发送消息为实例,代码如下:

package designpatterns;

import java.util.HashMap;
import java.util.Map.Entry;

/*
 * 中介者模式
 */
//先抽像一个使用者类(学生)
abstract class Person {
	String strName;	//姓名
	String strType;	//类型
	//每个人都有一个用来传递信息的中介List,如qq,email等
	HashMap<String, AbstractMediator> MyMediatorList = new HashMap<String, AbstractMediator>();
	public Person(String strName){
		this.strName = strName;
	}
	public String getStrName() {
		return strName;
	}
	public void setStrName(String strName) {
		this.strName = strName;
	}
	public String getStrType() {
		return strType;
	}
	public void setStrType(String strType) {
		this.strType = strType;
	}
	public void AddMediator(AbstractMediator MyMediator) {
		MyMediatorList.put(MyMediator.getStrName(), MyMediator);
	}
	//给所有人发消息
	public void SendMessageToAll(String MediatorName, String strMessage){
		MyMediatorList.get(MediatorName).SendMessageToAll(strMessage);
	}
	//给指定类型的人发消息
	public void SendMessageByType(String MediatorName, String strType, String strMessage) {
		MyMediatorList.get(MediatorName).SendMessageByType(strType, strMessage);
	}
	//给指定名字的人发消息
	public void SendMessageByName(String MediatorName, String strName, String strMessage) {
		MyMediatorList.get(MediatorName).SendMessageByName(strName, strMessage);
	}
	//接收消息
	public void ReciveMessage(String strMessage){
		System.out.println("[" + strType +"]" + "\"" + strName + "\"" + "收到"+strMessage);
	}
}
//定义学生
class Student extends Person {

	public Student(String strName) {
		super(strName);
		strType = "学生";
	}
}

//定义老师
class Teacher extends Person {

	public Teacher(String strName) {
		super(strName);
		strType = "老师";
	}
}
//定义校长
class Principal extends Person {

	public Principal(String strName) {
		super(strName);
		strType = "校长";
	}
}
//定义一个抽象中介
abstract class AbstractMediator {
	//中介的名字
	String strName;
	public AbstractMediator (String strName) {
		this.strName = strName;
	}
	public String getStrName() {
		return strName;
	}
	//定义一个人员列表
	HashMap<String, Person> PersonList = new HashMap<String, Person>();  
	public void addPerson(Person onePerson) {
		PersonList.put(onePerson.getStrName(), onePerson);
		onePerson.AddMediator(this);
	}
	public void deletePerson(String strName) {
		PersonList.remove(strName);
	}
	//给所有人发消息
	abstract public void SendMessageToAll(String strMessage);
	//给指定类型的人发消息
	abstract public void SendMessageByType(String strType, String strMessage);
	//给指定名字的人发消息
	abstract public void SendMessageByName(String strName, String strMessage);
}
//定义一个中介(QQ)用于传递消息
class QQMediator extends AbstractMediator{

	public QQMediator(String strName) {
		super(strName);
	}

	@Override
	public void SendMessageToAll(String strMessage) {
		String strQQMessage = "来自QQ消息:" + strMessage;
		for(Entry<String, Person> entry : PersonList.entrySet()){
			entry.getValue().ReciveMessage(strQQMessage);
		}
	}

	@Override
	public void SendMessageByType(String strType, String strMessage) {
		String strQQMessage = "来自QQ消息:" + strMessage;
		for(Entry<String, Person> entry : PersonList.entrySet()){
			if(strType == entry.getValue().getStrType())
			{
				entry.getValue().ReciveMessage(strQQMessage);
			}
		}
	}

	@Override
	public void SendMessageByName(String strName, String strMessage) {
		String strQQMessage = "来自QQ消息:" + strMessage;
		PersonList.get(strName).ReciveMessage(strQQMessage);
	}
	
}

//定义一个中介(Email)用于传递消息
class EmailMediator extends AbstractMediator{

	public EmailMediator(String strName) {
		super(strName);
	}

	@Override
	public void SendMessageToAll(String strMessage) {
		String strQQMessage = "来自Email消息:" + strMessage;
		for(Entry<String, Person> entry : PersonList.entrySet()){
			entry.getValue().ReciveMessage(strQQMessage);
		}
	}

	@Override
	public void SendMessageByType(String strType, String strMessage) {
		String strQQMessage = "来自Email消息:" + strMessage;
		for(Entry<String, Person> entry : PersonList.entrySet()){
			if(strType == entry.getValue().getStrType())
			{
				entry.getValue().ReciveMessage(strQQMessage);
			}
		}
	}

	@Override
	public void SendMessageByName(String strName, String strMessage) {
		String strQQMessage = "来自Email消息:" + strMessage;
		PersonList.get(strName).ReciveMessage(strQQMessage);
	}
	
}
public class Mediator {

	public static void main(String[] args) {
		//定义两个学生
		Student student1 = new Student("学生一");
		Student student2 = new Student("学生二");
		//定义两个老师
		Teacher teacher1 = new Teacher("老师一");
		Teacher teacher2 = new Teacher("老师二");
		//定义两个校长
		Principal principal1 = new Principal("校长一");
		Principal principal2 = new Principal("校长二");
		//定义两个中介(QQ和email)
		QQMediator myQQ = new QQMediator("qq");
		EmailMediator myEmail = new EmailMediator("email");
		//将所有人员分别添加到qq和email中
		myQQ.addPerson(student1);
		myQQ.addPerson(student2);
		myQQ.addPerson(teacher1);
		myQQ.addPerson(teacher2);
		myQQ.addPerson(principal1);
		myQQ.addPerson(principal2);
		myEmail.addPerson(student1);
		myEmail.addPerson(student2);
		myEmail.addPerson(teacher1);
		myEmail.addPerson(teacher2);
		myEmail.addPerson(principal1);
		myEmail.addPerson(principal2);
		//下面开始进行通信
		//首先"校长一"通过qq向"校长二"发一条消息
		principal1.SendMessageByName("qq", "校长二", "你觉得什么时候放假好?");
		principal2.SendMessageByName("qq", "校长一", "从明天开始放假吧!");
		principal1.SendMessageByName("qq", "校长二", "好的,那我发通知了");
		//然后"校长一"通过email向所有人员发一条消息
		principal1.SendMessageByType("email", "老师", "老师们都注意了,从明天开始放假");
		//老师收到消息后再给学生发消息
		teacher1.SendMessageByType("email", "学生", "同学们都注意了,从明天开始放假了!");
		//学生收到消息后,开始qq聊起来了
		student1.SendMessageByName("qq", "学生二", "明天放假了,我们去哪玩啊?");
		student2.SendMessageByName("qq", "学生一", "我们去爬山吧,再问问还有没有别人去!");
		student2.SendMessageToAll("email", "明天我们去爬山,还有没有一起去的?");
	}

}

  

二、使用中介者模式的场合和优缺点

使用终结者模式的场合

1.一组定义良好的对象,现在要进行复杂的通信。

2.定制一个分布在多个类中的行为,而又不想生成太多的子类。

可以看出,中介对象主要是用来封装行为的,行为的参与者就是那些对象,但是通过中介者,这些对象不用相互知道。呵呵~~~

使用中介者模式的优点:

1.降低了系统对象之间的耦合性,使得对象易于独立的被复用。

2.提高系统的灵活性,使得系统易于扩展和维护。

使用中介者模式的缺点:

中介者模式的缺点是显而易见的,因为这个“中介“承担了较多的责任,所以一旦这个中介对象出现了问题,那么整个系统就会受到重大的影响。

以上是关于设计模式--14中介者模式的主要内容,如果未能解决你的问题,请参考以下文章

14.中介者模式

设计模式中介者模式

设计模式------中介者模式

23种设计模式之中介者模式

23种设计模式之中介者模式

Head First设计模式之中介者模式