一.概述:中介者模式,定义了一个中介对象来封装一系列对象之间的交互关系。中介者使各个对象之间不需要显式地相互引用,从而使耦合性降低,而且可以独立地改变它们之间的交互行为。
二.例子:QQ游戏平台,聊天室、QQ群和短信平台,这些都是中介者模式在现实生活中的应用。
三.结构:
者模式设计两个具体对象,一个是用户类,另一个是中介者类,根据针对接口编程原则,则需要把这两类角色进行抽象,所以中介者模式中就有了4类角色,它们分别是:抽象中介者角色,具体中介者角色、抽象同事类和具体同事类。中介者类是起到协调各个对象的作用,则抽象中介者角色中则需要保存各个对象的引用。
四.实现:
假设英雄联盟中两个玩家之间的相互攻击,会造成双方的HP的改变。不使用中介者模式:
///
/// 抽象玩家类
///
public abstract class AbstractPlayer
{
///
/// 玩家生命值
///
public double HP { get; set; }
///
/// 遭受攻击时候,生命值减少,对应攻击者的HP增加
///
/// 修改数
/// 玩家
public abstract void ChangeHP(int num, AbstractPlayer player);
}
///
/// 玩家A adc
///
public class adcPlayerA:AbstractPlayer
{
///
/// 遭受攻击时候,A生命值减少,对应攻击者的HP增加
///
///
///
public override void ChangeHP(int num, AbstractPlayer player)
{
this.HP -= num;
player.HP = num * 0.1 + player.HP;
}
}
///
/// 玩家B ad
///
public class adPlayerB:AbstractPlayer
{
///
/// 遭受攻击时候,b生命值减少,对应攻击者的HP增加
///
///
///
public override void ChangeHP(int num, AbstractPlayer player)
{
this.HP -= num + player.HP * 0.01;
player.HP = player.HP + num * 0.01;
}
}
class Program
{
static void Main(string[] args)
{
AbstractPlayer a = new adcPlayerA();
a.HP = 200;
AbstractPlayer b = new adPlayerB();
b.HP = 500;
//a被b攻击
Console.WriteLine("a玩家遭受b的20点攻击");
a.ChangeHP(20, b);
Console.WriteLine("a生命值>" + a.HP);
Console.WriteLine("b生命值>" + b.HP);
Console.WriteLine("");
Console.WriteLine("b玩家遭受a的20点攻击");
b.ChangeHP(20, a);
Console.WriteLine("a生命值>" + a.HP);
Console.WriteLine("b生命值>" + b.HP);
}
}
上面使用了抽象类使具体玩家A和玩家B都依赖于抽象类,从而降低了同事类之间的耦合度。对于上面的设计可以有进一步完善的方案的,即加入一个中介者对象来协调各个对象之间的关联。下面通过中介者模式
///
/// 抽象玩家类
///
public abstract class AbstractPlayer
{
///
/// 玩家生命值
///
public double HP { get; set; }
///
/// 遭受攻击时候,生命值减少,对应攻击者的HP增加
///
///
///
public abstract void ChangeHP(int num, AbstractMediator Mediator);
}
///
/// 中介者抽象类
///
public abstract class AbstractMediator
{
protected AbstractPlayer A;
protected AbstractPlayer B;
public AbstractMediator(AbstractPlayer a, AbstractPlayer b)
{
A = a;
B = b;
}
///
/// A被B攻击
///
///
public abstract void AEmbattled(int num);
///
/// B被A攻击
///
///
public abstract void BEmbattled(int num);
}
///
/// 具体中介者
///
public class MediatorPater:AbstractMediator
{
private AbstractPlayer a;
private AbstractPlayer b;
public MediatorPater(AbstractPlayer a, AbstractPlayer b) : base(a, b) { }
public override void AEmbattled(int num)
{
A.HP -= num;
B.HP = num * 0.1 + B.HP;
}
public override void BEmbattled(int num)
{
B.HP -= num + A.HP * 0.01;
A.HP = A.HP + num * 0.01;
}
}
///
/// 玩家A adc
///
public class adcPlayerA:AbstractPlayer
{
///
/// 遭受攻击时候,A生命值减少,对应攻击者的HP增加
///
///
///
public override void ChangeHP(int num, AbstractMediator mediator)
{
mediator.AEmbattled(num);
}
}
///
/// 玩家B ad
///
public class adPlayerB:AbstractPlayer
{
///
/// 遭受攻击时候,b生命值减少,对应攻击者的HP增加
///
///
///
public override void ChangeHP(int num, AbstractMediator mediator)
{
mediator.BEmbattled(num);
}
}
///
/// C#设计模式-中介者模式
///
class Program
{
static void Main(string[] args)
{
AbstractPlayer a = new adcPlayerA();
a.HP = 200;
AbstractPlayer b = new adPlayerB();
b.HP = 500;
AbstractMediator mediator = new MediatorPater(a,b);
//a被b攻击
Console.WriteLine("a玩家遭受b的20点攻击");
a.ChangeHP(20, mediator);
Console.WriteLine("a生命值>" + a.HP);
Console.WriteLine("b生命值>" + b.HP);
Console.WriteLine("");
Console.WriteLine("b玩家遭受a的20点攻击");
b.ChangeHP(20, mediator);
Console.WriteLine("a生命值>" + a.HP);
Console.WriteLine("b生命值>" + b.HP);
}
}
从上面实现代码可以看出,此时玩家A和玩家B都依赖于抽象的中介者类,这样如果其中某个玩家类变化,只会影响到该变化玩家类本身和中介者类。
五.中介者模式的适用场景:
一组定义良好的对象,现在要进行复杂的相互通信。
想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
优点:
简化了对象之间的关系,将系统的各个对象之间的相互关系进行封装,将各个同事类解耦,使得系统变为松耦合。
提供系统的灵活性,使得各个同事对象独立而易于复用。
缺点:
中介者模式中,中介者角色承担了较多的责任,所以一旦这个中介者对象出现了问题,整个系统将会受到重大的影响。例如,QQ游戏中计算欢乐豆的程序出错了,这样会造成重大的影响。
新增加一个同事类时,不得不去修改抽象中介者类和具体中介者类,此时可以使用观察者模式和状态模式来解决这个问题。
中介者模式,定义了一个中介对象来封装系列对象之间的交互。
中介者使各个对象不需要显式地相互引用,从而使其耦合性降低,而且可以独立地改变它们之间的交互。
中介者模式一般应用于一组定义良好的对象之间需要进行通信的场合以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的情形下。