一个软件系统中往往包含了很多的类,这些类之间会存在互相的调用,随着系统的升级、功能的扩展,这些相互调用关系会变得非常复杂,,大量的相互连接使得这样一个类型系统不太可能在没有其他类支持的情况下独立完成工作,久而久之这些类将变得像一个不可分割的整体,内部有着错综复杂的关联。这会导致后期维护特别困难,对系统或模块的任何较大的变动都可能造成无法预知的问题。
中介者模式
中介者模式可以解决这种问题。它通过提供一个中介类,来处理不同类之间的通信,这样可以降低多个类之间的通信复杂度,使代码更易于维护。中介者模式属于行为型模式。通过应用Mediator模式,可以将类与类之间的多对多的关系转化成一对多的关系,从而降低了类之间的耦合。
GOF对中介者模式描述为:
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently..
— Design Patterns : Elements of Reusable Object-Oriented Software
UML类图:
代码实现
public interface IMediator<T>
{
void Operation();
void Register(IColleague<T> provider, params IColleague<T>[] consumers);
}
public interface IColleague<T>
{
T Data { get; set; }
IMediator<T> Mediator { get; set; }
}
public abstract class ColleagueBase<T> : IColleague<T>
{
public virtual T Data { get; set; }
private IMediator<T> mediator;
public virtual IMediator<T> Mediator
{
get
{
return mediator;
}
set
{
mediator = value;
}
}
}
public class Mediator<T> : IMediator<T>
{
private IColleague<T> provider;
private IList<IColleague<T>> consumers;
public void Operation()
{
if (provider != null && consumers != null && consumers.Count > 0)
{
foreach (var item in consumers)
{
item.Data = provider.Data;
}
}
}
public void Register(IColleague<T> provider, params IColleague<T>[] consumers)
{
this.provider = provider;
if (consumers != null && consumers.Length > 0)
{
this.consumers = new List<IColleague<T>>(consumers);
}
}
}
public class ConcreteColleagueA : ColleagueBase<int>
{
public override int Data
{
get => base.Data;
set
{
base.Data = value;
base.Mediator.Operation();
}
}
}
public class ConcreteColleagueB : ColleagueBase<int>
{
}
public class ConcreteColleagueC : ColleagueBase<int>
{
}
调用端:
public class Test
{
public static void Entry()
{
Mediator<int> mA2BC = new Mediator<int>();
ConcreteColleagueA a = new ConcreteColleagueA();
ConcreteColleagueB b = new ConcreteColleagueB();
ConcreteColleagueC c = new ConcreteColleagueC();
a.Mediator = b.Mediator = c.Mediator = mA2BC;
mA2BC.Register(a, b, c);
a.Data = 20;
Console.WriteLine($"a:{a.Data},b:{b.Data}, c:{c.Data}"); //a:20,b:20,c:20
mA2BC.Register(a, b);
a.Data = 30;
Console.WriteLine($"a:{a.Data},b:{b.Data}, c:{c.Data}"); //a:30,b:30,c:20
}
}
适用场景
- 系统中对象之间存在比较复杂的引用关系,导致他们之间的依赖关系结构混乱而且难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
优缺点
优点
- 降低了系统类的复杂度,将一对多转化成了一对一,只需要与中介者交互
- 中介者模式使得对象之间不需要显式地相互引用,从而使得系统或模块内部相互解耦。
- 符合迪米特原则
缺点
由于中介者对象封装了各个类之间的交互,会导致中介者类本身的复杂性上升,会有一定的维护成本
参考书籍:
王翔著 《设计模式——基于C#的工程化实现及扩展》
网友评论