中介者模式简介
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。
中介者模式的优点:
- 简化了对象之间的关系,将系统的各个对象之间的相互关系进行封装,将各个同事类解耦,使得系统变为松耦合。
- 提供系统的灵活性,使得各个同事对象独立而易于复用。
中介者模式的缺点:
- 中介者模式中,中介者角色承担了较多的责任,所以一旦这个中介者对象出现了问题,整个系统会受到重大的影响。例如,QQ游戏中计算欢乐豆的程序出错了,这样会造成重大的影响。
- 新增加一个同事类时,不得不去修改抽象中介者类和具体中介者类,此时可以使用观察者模式和状态模式来解决这个问题。
中介者模式UML图
下图是不使用中介者模式的情况,各个对象或者各个模块需要访问对方,必须要进行相互的引用,此时代码的耦合度很高,如果一个对象或者一个模块发生改变势必会引起其他模块的改变,而且这种结构不利于类的服用和拓展,也不利于代码的维护。
很明显,上述的实现方式并不合理,我们可以使用中介者模式来解决这一类的问题,提供一个中介者的类,每个模块或者对象要访问其他模块必须通过中介者来操作,此时只会有本类和中介者状态发生改变,不会引起其他模块的改变,这样的设计大大降低了耦合度。
中介者模式简单实现
在现实生活中,两个人打牌,如果某个人赢了都会影响到对方状态的改变。如果此时不采用中介者模式实现的话,则上面的场景的实现如下所示:
不采用中介者模式的实现方式:
AbstractCardPlayer(抽象的玩家类):
using System;
namespace MediatorPatternDemo
{
public abstract class AbstractCardPlayer
{
public int coinCount; //金币数
public AbstractCardPlayer(int count)
{
this.coinCount = count;
}
public abstract void WinCoinCount(int count, AbstractCardPlayer other);
}
}
PlayerA :
using System;
namespace MediatorPatternDemo
{
public class PlayerA : AbstractCardPlayer
{
public PlayerA(int count) : base(count)
{
}
public override void WinCoinCount(int count, AbstractCardPlayer other)
{
this.coinCount += count;
other.coinCount -= count;
}
}
}
PlayerB :
using System;
namespace MediatorPatternDemo
{
public class PlayerB : AbstractCardPlayer
{
public PlayerB(int count) : base(count)
{
}
public override void WinCoinCount(int count, AbstractCardPlayer other)
{
this.coinCount += count;
other.coinCount -= count;
}
}
}
using System;
namespace MediatorPatternDemo
{
class Program
{
static void Main(string[] args)
{
AbstractCardPlayer playerA = new PlayerA(1000);
AbstractCardPlayer playerB = new PlayerB(2000);
//playerA赢了playerB的金币
playerA.WinCoinCount(300, playerB);
//playerB赢了playerA的金币
playerB.WinCoinCount(200, playerA);
}
}
}
上面确实完美解决了上面场景中的问题,并且使用了抽象类使具体牌友A和牌友B都依赖于抽象类,从而降低了同事类之间的耦合度。但是这样的设计,如果其中牌友A发生变化时,此时就会影响到牌友B的状态,如果涉及的对象变多的话,这时候某一个牌友的变化将会影响到其他所有相关联的牌友状态。例如牌友A算错了钱,这时候牌友A和牌友B的钱数都不正确了,如果是多个人打牌的话,影响的对象就会更多。这时候就会思考——能不能把算钱的任务交给程序或者算数好的人去计算呢,这时候就有了我们QQ游戏中的欢乐斗地主等牌类游戏了。所以上面的设计,我们还是有进一步完善的方案的,即加入一个中介者对象来协调各个对象之间的关联,这也就是中介者模式的应用了,具体完善后的实现代码如下所示:
采用中介者模式的实现方式:
AbstractCardPlayer:
using System;
namespace MediatorPatternDemo
{
public abstract class AbstractCardPlayer
{
public int coinCount; //金币数
protected AbstractMediator mediator; //对中介者的引用
public AbstractCardPlayer(int count,AbstractMediator mediator)
{
this.coinCount = count;
this.mediator = mediator;
}
public abstract void WinCoinCount(int count);
}
}
PlayerA:
using System;
namespace MediatorPatternDemo
{
public class PlayerA : AbstractCardPlayer
{
public PlayerA(int count,AbstractMediator mediator) : base(count, mediator)
{
mediator.playerA = this;
}
public override void WinCoinCount(int count)
{
mediator.AWinCoin(count);
}
}
}
PlayerB :
using System;
namespace MediatorPatternDemo
{
public class PlayerB : AbstractCardPlayer
{
public PlayerB(int count, AbstractMediator mediator) : base(count, mediator)
{
mediator.playerB = this;
}
public override void WinCoinCount(int count)
{
mediator.BWinCoin(count);
}
}
}
AbstractMediator(抽象的中介者类):
using System;
namespace MediatorPatternDemo
{
public abstract class AbstractMediator
{
public AbstractCardPlayer playerA;
public AbstractCardPlayer playerB;
public AbstractMediator()
{
}
public abstract void AWinCoin(int count);
public abstract void BWinCoin(int count);
}
}
Mediator (中介者类):
using System;
namespace MediatorPatternDemo
{
public class Mediator : AbstractMediator
{
public Mediator()
{
}
public override void AWinCoin(int count)
{
}
public override void BWinCoin(int count)
{
}
}
}
using System;
namespace MediatorPatternDemo
{
class Program
{
static void Main(string[] args)
{
AbstractMediator mediator = new Mediator();
AbstractCardPlayer playerA = new PlayerA(1000, mediator);
AbstractCardPlayer playerB = new PlayerB(2000, mediator);
//playerA赢了playerB的金币
playerA.WinCoinCount(300);
//playerB赢了playerA的金币
playerB.WinCoinCount(200);
}
}
}