定义
从生活中的例子可以看出,不论是QQ群还是QQ游戏,他们都是充当一个中间平台,QQ用户可以登录这个中间平台与其他QQ用户交流,如果没有这些中间平台,我们想与朋友聊天的话,可能就需要面对面才行了。电话,短信也是一样的,有了这个中间平台。每个用户都不用直接依赖于其他用户,只需要依赖这个平台就可以了,一切操作都由中间平台去分发。
中介者模式,定义了一个中介对象来封装一系列对象之间的交互关系。中介者使各个对象之间不需要显式地相互引用,从而是耦合性降低,而且可以独立改变它们之间的交互行为。
结构
中介者模式设计两个具体对象,一个是用户类,一个是中介者类,根据针对接口编程原则,则需要把这两个类进行抽象,所以中介者模式中就有4种角色:抽象中介者角色、具体中介者角色、抽象用户类、具体用户类。中介者类起到协调各个对象的作用,则抽象中介者角色中则需要保存各个对象的引用。
为什么使用中介者模式?
在现实生活中,中介者的存在是必不可少的,如果没有了中介者,我们就不能与远方的朋友进行交流。在软件设计领域,如果不使用中介者模式的话,各个对象将会相互进行引用,如果每个对象都与多个对象进行交互时,将会呈现一种网状结构。
如果引用了中介者模式,那么对象间的关系将变成星型结构。星型结构相比网状结构的好处在于,一个对象变化,只会引起对象本身和中介者的变化,而不会影响到其他对象。这样的设计,大大减少了系统的耦合度。
实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _34MediatorPatternDemo
{
//抽象牌友类
public abstract class AbstractCardPatner
{
public int MoneyCount { get; set; }
public AbstractCardPatner()
{
MoneyCount = 0;
}
public abstract void ChangeCount(int Count, AbstractMediator mediator);
}
//具体牌友类
public class ParterA : AbstractCardPatner
{
//依赖与抽象中介者对象
public override void ChangeCount(int Count, AbstractMediator mediator)
{
mediator.AWin(Count);
}
}
public class ParterB : AbstractCardPatner
{
//依赖与抽象中介者对象
public override void ChangeCount(int Count, AbstractMediator mediator)
{
mediator.BWin(Count);
}
}
//抽象中介者类
public abstract class AbstractMediator
{
protected AbstractCardPatner A;
protected AbstractCardPatner B;
public AbstractMediator(AbstractCardPatner a, AbstractCardPatner b)
{
A = a;
B = b;
}
public abstract void AWin(int count);
public abstract void BWin(int count);
}
//具体中介者类
public class MediatorPater : AbstractMediator
{
public MediatorPater(AbstractCardPatner a, AbstractCardPatner b) : base(a, b)
{
}
public override void AWin(int count)
{
A.MoneyCount += count;
B.MoneyCount -= count;
}
public override void BWin(int count)
{
A.MoneyCount -= count;
B.MoneyCount += count;
}
}
//客户端类
class Program
{
static void Main(string[] args)
{
AbstractCardPatner A = new ParterA();
AbstractCardPatner B = new ParterB();
//初始化钱
A.MoneyCount = 20;
B.MoneyCount = 30;
AbstractMediator mediator = new MediatorPater(A, B);
//A赢了
A.ChangeCount(5, mediator);
Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是25
Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是25
//继续打,B赢了
B.ChangeCount(10, mediator);
Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是15
Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是35
}
}
}
在上面的实现代码中,抽象中介者类保存了两个抽象牌友类,如果新添加一个牌友类似时,此时就不得不去更改这个抽象中介者类。可以结合观察者模式来解决这个问题,即抽象中介者对象保存抽象牌友的类别,然后添加Register和UnRegister方法来对该列表进行管理,然后在具体中介者类中修改AWin和BWin方法,遍历列表,改变自己和其他牌友的钱数。这样的而设计还存在一个问题——即增加一个新牌友时,此时虽然解决了抽象中介者类不需要修改的问题,但此时还是要去修改具体中介者类,即添加CWin方法,我们可以使用状态模式来解决这个问题(下一章讲)。
适用场景
- 一组定义良好的对象,现在要进行复杂的相互通信
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类
优缺点
优点:
- 简化了对象之间的关系,将系统的各个对象之间的相互关系进行封装,将各个同事类解耦,使得系统变为松耦合。
- 提供系统的灵活性,使得各个同事对象独立而易于复用。
缺点:
- 中介者模式中,中介者角色承担了较多的责任,所以一旦这个中介者对象出现了问题,整个系统将会受到重大的影响。例如,QQ游戏中计算欢乐豆的程序出错了,这样会造成重大的影响。
- 新增加一个相同类时,不得不去修改抽象中介者类和具体中介者类,此时可以使用观察者模式和状态模式来解决这个问题。
总结
中介者模式,定义了一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显式地相互引用,从而使其耦合性降低,而且可以独立地改变它们之间的交互。中介者模式一般应用于一组定义良好的对象之间需要进行通信的场合以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的情形下。