语言与模式-20中介者模式
意图
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
适用性
- 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类。
Java实现
//抽象同事类
public abstract class Person {
// 维持一个抽象中介者的引用
protected Mediator mediator;
protected String name;
public Person(String name, Mediator mediator){
this.mediator = mediator;
this.name = name;
}
/**
* 设置中介者对象
* @param mediator
*/
public void setMediator(Mediator mediator){
this.mediator = mediator;
}
/**
* 向中介 发送消息
*/
protected abstract void sendMessage(String msg);
/**
* 从中介 获取消息
*/
protected abstract void getMessage(String msg);
}
//具体同事类:这里的角色是 租房者
public class Renter extends Person {
public Renter(String name, Mediator mediator) {
super(name, mediator);
}
@Override
protected void sendMessage(String msg) {
mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
System.out.println("求租者[" + name + "]收到中介发来的消息: " + msg);
}
}
//具体同事类:这里的角色是 房东
public class Landlord extends Person {
public Landlord(String name, Mediator mediator) {
super(name,mediator);
}
@Override
protected void sendMessage(String msg) {
mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
System.out.println("房东["+ name +"]收到中介发来的消息:" + msg);
}
}
//抽象中介者类
public abstract class Mediator {
// 用于添加储存 "房东"角色
protected List<Person> landlordList = new ArrayList<Person>();
// 用于添加储存 "求租者"角色
protected List<Person> renterList = new ArrayList<Person>();
/**
* 中介者注册房东信息
* @param landlord 房东实体
*/
public void registerLandlord(Person landlord){
landlordList.add(landlord);
}
/**
* 中介者注册 求租者信息
* @param landlord 房东实体
*/
public void registerRenter(Person landlord){
renterList.add(landlord);
}
/**
* 声明抽象方法 由具体中介者子类实现 消息的中转和协调
*/
public abstract void operation(Person person, String message);
}
//具体中介者类:这里的角色是 房屋出租中介
public class HouseMediator extends Mediator {
@Override
public void operation(Person person, String message) {
if(person instanceof Renter){
// 将租屋的需求消息传递给 注册了的房东们
for(Person landlord: landlordList){
landlord.getMessage(message);
}
} else if(person instanceof Landlord){
// 将房东的出租房消息传递给 注册了的 房屋求租者们
for(Person renter : renterList){
renter.getMessage(message);
}
}
}
}
//客户端测试类
public class Client {
public static void main(String[] args) {
// 实例化房屋中介
Mediator mediator = new HouseMediator();
Person landlordA, landlordB, renter;
landlordA = new Landlord("房东李", mediator);
landlordB = new Landlord("房东黎", mediator);
renter = new Renter("小吕",mediator);
// 房东注册中介
mediator.registerLandlord(landlordA);
mediator.registerLandlord(landlordB);
// 求租者注册中介
mediator.registerRenter(renter);
// 求租者 发送求租消息
renter.sendMessage("在天河公园附近租套房子,价格1000元左右一个月");
System.out.println("--------------------------");
// 房东A 发送房屋出租消息
landlordA.sendMessage("天河公园学院站三巷27号四楼有一房一厅出租 1200/月 光线好 近公交站");
}
}
Clojure实现
中介者模式类似双向的观察者模式!
观察者模式是单向的,从Subject向多个Observer传递信息!
中介者模式相当与ObserverA向Subject传递信息,再通过Subject传递给ObserverB,反之亦然!
那么就可以通过实现两个add-watch来实现类似中介者模式!
(def a (atom {}))
(def b (atom {}))
(defn func-a []
(println "func-a invoke"))
(defn func-b []
(println "func-b invoke"))
(add-watch a :watcherA
(fn [key atom old-state new-state]
(func-a)))
(add-watch b :watcherB
(fn [key atom old-state new-state]
(func-b)))
(reset! a {:foo "bar"})
(reset! b {:foo "bar"})