中介者模式

《大话设计模式》第25章读书笔记,介绍中介者模式

Posted by GrayWind on November 21, 2018

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

mediator

Mediator类,抽象中介者类,定义个抽象的发生消息方法,得到同事对象和发送消息

public interface Mediator {
	public void send(String message, Colleague colleague);
}

Colleague类,抽象同事类,构造时得到中介者对象

public abstract class Colleague {
	protected Mediator mediator;

	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}

	public abstract void send(String message);

	public abstract void notify(String message);
}

ConcreteMediator类,具体中介者对象,需要了解所有的具体同事对象。发送消息时,根据对象作出选择判断,通知对象

public class ConcreteMediator implements Mediator {
	private ConcreteColleague1 colleague1;
	private ConcreteColleague2 colleague2;

	public void setColleague1(ConcreteColleague1 colleague1) {
		this.colleague1 = colleague1;
	}

	public void setColleague2(ConcreteColleague2 colleague2) {
		this.colleague2 = colleague2;
	}

	@Override
	public void send(String message, Colleague colleague) {
		//colleague是否能被转换为colleague1的类
		if (colleague1.getClass().isInstance(colleague)) {
			colleague2.notify(message);
		} else {
			colleague1.notify(message);
		}
	}

}

具体同事对象类,发送消息时是通过中介者发送出去的

public class ConcreteColleague1 extends Colleague {

	public ConcreteColleague1(Mediator mediator) {
		super(mediator);
	}

	@Override
	public void send(String message) {
		mediator.send(message, this);
	}

	@Override
	public void notify(String message) {
		System.out.println("同事1得到消息:" + message);		
	}

}

public class ConcreteColleague2 extends Colleague {

	public ConcreteColleague2(Mediator mediator) {
		super(mediator);
	}

	@Override
	public void send(String message) {
		mediator.send(message, this);
	}

	@Override
	public void notify(String message) {
		System.out.println("同事2得到消息:" + message);		
	}

}

客户端调用

public class Test {
	public static void main(String[] args) {
		ConcreteMediator m = new ConcreteMediator();

        ConcreteColleague1 c1 = new ConcreteColleague1(m);
        ConcreteColleague2 c2 = new ConcreteColleague2(m);

        m.setColleague1(c1);
        m.setColleague2(c2);

        c1.send("吃过饭了吗?");//同事2得到消息:吃过饭了吗?
        c2.send("没有呢,你打算请客?");//同事1得到消息:没有呢,你打算请客?
	}
}

尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增又会降低其可复用性。因为大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难。

中介者模式中Mediator的出现减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague类和Mediator。由于把对象如何写作进行了抽象,将终结作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。但是,由于ConcreteMediator控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。

所以,中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,以及想定制一个分布在多个类中的行为,而又不想生成太多子类的场合。当系统中出现了多对多交互复杂的对象群时,不要急于使用中介者模式,而要先反思在系统设计上是否不合理。


下面这个例子中美国和伊拉克之间通过联合国进行中介调停就是一个典型的中介者模式。

联合国类,相当于Mediator类

public interface UnitedNations {
	public void declare(String message, Country colleague);
}

国家类,相当于Colleague类

public abstract class Country {
	protected UnitedNations mediator;

	public Country(UnitedNations mediator) {
		this.mediator = mediator;
	}

	public abstract void declare(String message);

	public abstract void getMessage(String message);
}

美国类,相同于ConcreteColleague1类

public class USA extends Country{

	public USA(UnitedNations mediator) {
		super(mediator);
	}

	@Override
	public void declare(String message) {
		mediator.declare(message, this);
	}

	@Override
	public void getMessage(String message) {
		System.out.println("美国获得对方信息:" + message);
	}

}

伊拉克类,相当于ConcreteColleague2类

public class Iraq extends Country{

	public Iraq(UnitedNations mediator) {
		super(mediator);
	}

	@Override
	public void declare(String message) {
		mediator.declare(message, this);
	}

	@Override
	public void getMessage(String message) {
		System.out.println("伊拉克获得对方信息:" + message);
	}

}

联合国安理会,相当于ConcreteMediator类

public class UnitedNationsSecurityCouncil implements UnitedNations {
	private USA colleague1;
	private Iraq colleague2;

	public void setColleague1(USA colleague1) {
		this.colleague1 = colleague1;
	}

	public void setColleague2(Iraq colleague2) {
		this.colleague2 = colleague2;
	}

	@Override
	public void declare(String message, Country colleague) {
		if (colleague1.getClass().isInstance(colleague)) {
			colleague2.getMessage(message);
		} else {
			colleague1.getMessage(message);
		}

	}

}

客户端类

public class CountryTest {
	public static void main(String[] args) {
		UnitedNationsSecurityCouncil UNSC = new UnitedNationsSecurityCouncil();

        USA c1 = new USA(UNSC);
        Iraq c2 = new Iraq(UNSC);

        UNSC.setColleague1(c1);
        UNSC.setColleague2(c2);

        c1.declare("不准研制核武器,否则要发动战争!");//伊拉克获得对方信息:不准研制核武器,否则要发动战争!
        c2.declare("我们没有核武器,也不怕侵略。");//美国获得对方信息:我们没有核武器,也不怕侵略。
	}
}