概述:
如果在一个系统中对象之间的联系呈现为网状结构,如图1-1所示。对象之间存在大量的多对多联系,将导致系统非常复杂,这些对象既会影响别的对象, 也会被别的对象所影响,这些对象称为同事对象,它们之间通过彼此的相互作用实现系统的行为。在网状结构中,几乎每个对象都需要与其他对象发生相互作用, 而这种相互作用表现为一个对象与另外一个对象的直接耦合,这将导致一个过度耦合的系统。
图1-1
中介者模式可以使对象之间的关系数量急剧减少,通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,如图1-2所示。在这个星形结构中,同事对象不再直接与另一个对象联系,它通过中介者对象与另一个对象发生相互作用。中介者对象的存在保证了对象结构上的稳定,也就是说,系统的结构不会因为新对象的引入带来大量的修改工作。
图1-2
定义:
用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
结构:
- Mediator(抽象中介者):它定义一个接口,该接口用于与各同事对象之间进行通信。
- ConcreteMediator(具体中介者):它是抽象中介者的子类,通过协调各个同事对象来实现协作行为,它维持了对各个同事对象的引用。
- Colleague(抽象同事类):它定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
- ConcreteColleague(具体同事类):它是抽象同事类的子类;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。
UML图:
场景:大家应该租房过吧,租客和房东之间的关系应该就是多对多的关系,对于租客来说只要满足自己的需求的房子就可以选择,同理,房东也一样了。但是如果你自己想租房的话,人生地不熟的,你根本不知道哪里有房子需要出租,而且就算找到房东,你也必须一个一个房东的问,看看是否符合自己的需要,所以为了快速高效的找到租房,只能求助第三方了,可以找中介(虽然很坑),因为中介有大量的房东信息,你只需要将需求告诉他,然后很快就能帮你找到。
代码分析:
/**
* Created by **
* 定义抽象的同事类
*/
public abstract class AbstractColleague {
protected AbstractMediator mediator;
public AbstractColleague(AbstractMediator mediator){
this. mediator = mediator;
}
}
* Created by **
* 定义抽象的同事类
*/
public abstract class AbstractColleague {
protected AbstractMediator mediator;
public AbstractColleague(AbstractMediator mediator){
this. mediator = mediator;
}
}
/**
* Created by **
* 定义房东抽象类,因为房东跟租客有不同的方法,所以将房东和房客分开来
*/
public abstract class AbstractLandlord extends AbstractColleague {
public AbstractLandlord(AbstractMediator mediator) {
super(mediator);
}
/**
* 房租租金
* @return
*/
protected abstract int getPrice();
/**
* 出租房屋
*/
protected abstract void HouseForRent();
}
* Created by **
* 定义房东抽象类,因为房东跟租客有不同的方法,所以将房东和房客分开来
*/
public abstract class AbstractLandlord extends AbstractColleague {
public AbstractLandlord(AbstractMediator mediator) {
super(mediator);
}
/**
* 房租租金
* @return
*/
protected abstract int getPrice();
/**
* 出租房屋
*/
protected abstract void HouseForRent();
}
/**
* Created by **
* 具体房东类
*/
public class LandlordA extends AbstractLandlord{
private final int RENT = 3000;
public LandlordA(AbstractMediator mediator) {
super(mediator);
}
/**
* 出租房屋
*/
@Override
public void HouseForRent(){
LogFactory. log( " 出租小 A 的房屋 ");
}
/**
* 房租租金
* @return
*/
@Override
public int getPrice(){
return RENT;
}
}
* Created by **
* 具体房东类
*/
public class LandlordA extends AbstractLandlord{
private final int RENT = 3000;
public LandlordA(AbstractMediator mediator) {
super(mediator);
}
/**
* 出租房屋
*/
@Override
public void HouseForRent(){
LogFactory. log( " 出租小 A 的房屋 ");
}
/**
* 房租租金
* @return
*/
@Override
public int getPrice(){
return RENT;
}
}
/**
* Created by **
* 具体房东类
*/
public class LandlordB extends AbstractLandlord {
private final int RENT = 1000;
public LandlordB(AbstractMediator mediator) {
super(mediator);
}
@Override
public void HouseForRent(){
LogFactory. log( " 出租小 B 的房屋 ");
}
@Override
public int getPrice(){
return RENT;
}
}
* Created by **
* 具体房东类
*/
public class LandlordB extends AbstractLandlord {
private final int RENT = 1000;
public LandlordB(AbstractMediator mediator) {
super(mediator);
}
@Override
public void HouseForRent(){
LogFactory. log( " 出租小 B 的房屋 ");
}
@Override
public int getPrice(){
return RENT;
}
}
/**
* Created by **
* 租客抽象类
*/
public abstract class AbstractTenant extends AbstractColleague {
public AbstractTenant(AbstractMediator mediator) {
super(mediator);
}
/**
* 设定租房条件:租金
* @param startPrice
* @param endPrice
*/
protected abstract void RentalsCondition( int startPrice, int endPrice);
}
* Created by **
* 租客抽象类
*/
public abstract class AbstractTenant extends AbstractColleague {
public AbstractTenant(AbstractMediator mediator) {
super(mediator);
}
/**
* 设定租房条件:租金
* @param startPrice
* @param endPrice
*/
protected abstract void RentalsCondition( int startPrice, int endPrice);
}
/**
* Created by **
* 小明:具体租客
*/
public class XiaoMing extends AbstractTenant {
public XiaoMing(AbstractMediator mediator) {
super(mediator);
}
@Override
public void RentalsCondition( int startPrice, int endPrice){
LogFactory. log( " 我想租价格在 " + startPrice + "~" + endPrice + " 的房子 ");
mediator.handleTenantReuqests(startPrice, endPrice);
}
}
* Created by **
* 小明:具体租客
*/
public class XiaoMing extends AbstractTenant {
public XiaoMing(AbstractMediator mediator) {
super(mediator);
}
@Override
public void RentalsCondition( int startPrice, int endPrice){
LogFactory. log( " 我想租价格在 " + startPrice + "~" + endPrice + " 的房子 ");
mediator.handleTenantReuqests(startPrice, endPrice);
}
}
/**
* Created by **
* 中介者抽象类
*/
public abstract class AbstractMediator {
protected LandlordA landlordA;
protected LandlordB landlordB;
protected XiaoMing xiaoMing;
protected List<AbstractLandlord> listLandlords;
public AbstractMediator(){
listLandlords = new ArrayList<AbstractLandlord>();
this. landlordA = new LandlordA( this);
this. landlordB = new LandlordB( this);
this. xiaoMing = new XiaoMing( this);
initRentersInfo();
}
private void initRentersInfo(){
this. listLandlords.add( landlordA);
this. listLandlords.add( landlordB);
}
/**
* 处理租客的租房请求
* @param startPrice
* @param endPrice
*/
public abstract void handleTenantReuqests( int startPrice, int endPrice);
}
* Created by **
* 中介者抽象类
*/
public abstract class AbstractMediator {
protected LandlordA landlordA;
protected LandlordB landlordB;
protected XiaoMing xiaoMing;
protected List<AbstractLandlord> listLandlords;
public AbstractMediator(){
listLandlords = new ArrayList<AbstractLandlord>();
this. landlordA = new LandlordA( this);
this. landlordB = new LandlordB( this);
this. xiaoMing = new XiaoMing( this);
initRentersInfo();
}
private void initRentersInfo(){
this. listLandlords.add( landlordA);
this. listLandlords.add( landlordB);
}
/**
* 处理租客的租房请求
* @param startPrice
* @param endPrice
*/
public abstract void handleTenantReuqests( int startPrice, int endPrice);
}
/**
* Created by **
*/
public class Mediator extends AbstractMediator {
public Mediator() {
super();
}
@Override
public void handleTenantReuqests( int startPrice, int endPrice) {
LogFactory. log( "dealWhitRenters startPrice = " + startPrice + ",endPrice = " + endPrice);
for ( int i = 0; i < super. listLandlords.size(); i++) {
AbstractLandlord landlord = super. listLandlords.get(i);
int price = landlord.getPrice();
LogFactory. log( "price = " + price);
if (price > startPrice && price < endPrice) {
landlord.HouseForRent();
} else {
LogFactory. log( " 找不到匹配的房屋 ");
}
}
}
}
* Created by **
*/
public class Mediator extends AbstractMediator {
public Mediator() {
super();
}
@Override
public void handleTenantReuqests( int startPrice, int endPrice) {
LogFactory. log( "dealWhitRenters startPrice = " + startPrice + ",endPrice = " + endPrice);
for ( int i = 0; i < super. listLandlords.size(); i++) {
AbstractLandlord landlord = super. listLandlords.get(i);
int price = landlord.getPrice();
LogFactory. log( "price = " + price);
if (price > startPrice && price < endPrice) {
landlord.HouseForRent();
} else {
LogFactory. log( " 找不到匹配的房屋 ");
}
}
}
}
客户端:
AbstractMediator mediator =
new Mediator();
LogFactory. log( "--------- 租房 -----");
XiaoMing xiaoMing = new XiaoMing(mediator);
xiaoMing.RentalsCondition( 800, 1500);
LogFactory. log( "--------- 租房 -----");
XiaoMing xiaoMing = new XiaoMing(mediator);
xiaoMing.RentalsCondition( 800, 1500);
log输出:
08-16 14:08:23.191 18206-18206/? D/test: ---------租房-----
08-16 14:08:23.191 18206-18206/? D/test: 我想租价格在800~1500的房子
08-16 14:08:23.191 18206-18206/? D/test: dealWhitRenters startPrice = 800,endPrice = 1500
08-16 14:08:23.191 18206-18206/? D/test: price = 3000
08-16 14:08:23.191 18206-18206/? D/test: 找不到匹配的房屋
08-16 14:08:23.191 18206-18206/? D/test: price = 1000
08-16 14:08:23.191 18206-18206/? D/test: 出租小B的房屋
优点:
- 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
- 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
- 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。
- 可以简化各同事类的设计和实现。
缺点:
- 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
适用环境:
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。
- 交互的公共行为,如果需要改变行为则可以增加新的中介者类。
扩展:
中介者模式与迪米特法则
- 在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用。
中介者模式与GUI开发
- 中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。
- 对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。