中介者模式(Mediator Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/419 访问。

中介者模式属于行为型模式,它包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散耦合。

当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。

角色:

1、抽象中介者(Mediator):

定义统一的接口用于各同事角色之间的通信,其中主要方法是一个(或多个)事件方法;

2、具体中介者(Concrete Mediator):

实现了抽象中介者所声明的事件方法。具体中介者知晓所有的具体同事类,并负责具体的协调各同事对象的交互关系;

3、抽象同事类(Colleague):

定义出中介者到同事角色的接口。同事角色只知道中介者而不知道其余的同事角色。与其他的同事角色通信的时候,一定要通过中介者角色协作;

4、具体同事类(Concrete Colleague):

所有的具体同事类均从抽象同事类继承而来。实现自己的业务,在需要与其他同事通信的时候,就与持有的中介者通信,中介者会负责与其他的同事交互。

示例:

命名空间MediatorPattern中包含抽象用户类User充当同事基类,它有2个实现类,普通用户GeneralUser类和VIP用户VipUser类,聊天室ChatRoom类充当中介者基类,新浪聊天室SinaChat类为具体中介者。本案例尝试使用中介者模式实现应用最为广泛的网络聊天室。

namespace MediatorPattern
public abstract class User {

    public string Name { get; private set; }

    protected User(string name) {
Name = name;
} public abstract void OnRecieve(User sender, string message, bool group = false); }

抽象用户类User,内部仅维持一个姓名,OnRecieve方法定义在收到其他用户的信息时的回调。此处必须使用public公开OnRecieve方法,因为在聊天室中需要调用它。

C#开发笔记之02-什么时候使用OnXXX方法,这种命名是什么意思?

public class GeneralUser : User {

    public GeneralUser(string name) : base(name) {

    }

    public override void OnRecieve(User sender, string message, bool group = false) {
var groupFlag = group ? "group" : "private";
Console.WriteLine(
$"{this.IdentitySign()} recieved a {groupFlag} message from " +
$"{sender.IdentitySign()},{Environment.NewLine}(s)he says:{message}");
} }

普通用户类GeneralUser,继承自User并实现OnRecieve方法。

public class VipUser : User {

    public VipUser(string name) : base(name) {

    }

    public override void OnRecieve(User sender, string message, bool group = false) {
var groupFlag = group ? "group" : "private";
Console.WriteLine(
$"{this.IdentitySign()} recieved a {groupFlag} message from " +
$"{sender.IdentitySign()},{Environment.NewLine}(s)he says:{message}");
} }

Vip用户类VipUser,继承自User并实现OnRecieve方法。实际开发过程中可不定义2个实现类,使用属性标识是否是Vip用户即可。

public abstract class ChatRoom {

    protected List<User> _users = null;

    protected const string SPLIT_BREAK =
"------------------------------------------------------"; protected ChatRoom() {
_users = new List<User>();
} public void Attach(User user) {
if (user == null) throw new ArgumentNullException();
_users.Add(user);
} public bool Detach(User user) {
if (user == null) throw new ArgumentNullException();
return _users.Remove(user);
} public abstract void Talk2All(User sender, string message);
public abstract void Talk2User(User sender, User reciever, string message); }

聊天室基类ChatRoom,需要维持对User列表的引用并包含添加和删除方法,包含2个主要方法,对所有人说话Talk2All和对某人说话Talk2User。

public class SinaChat : ChatRoom {

    public override void Talk2All(User sender, string message) {
_users.Where(u => u.Name != sender.Name)
.ToList()
.ForEach((u) => u.OnRecieve(sender, message, true));
Console.WriteLine(SPLIT_BREAK);
} public override void Talk2User(User sender, User reciever, string message) {
var user = _users.Where(u => u.Name == reciever.Name)
.FirstOrDefault();
user.OnRecieve(sender, message);
Console.WriteLine(SPLIT_BREAK);
} }

具体聊天室,实现对所有人说话Talk2All和对某人说话Talk2User方法。

public static class Extentions {

    public static string IdentitySign(this User user) {
if (user is VipUser) {
return $"{user.Name}[VIP]";
}
else if (user is GeneralUser) {
return $"{user.Name}";
}
return string.Empty;
} }

定义了一个扩展以方便展示用户Vip标识。

public class Program {

    private static ChatRoom _chatRoom;

    public static void Main(string[] args) {
_chatRoom = new SinaChat(); var juice = new GeneralUser("Juice");
var cola = new GeneralUser("Cola");
var iori = new VipUser("Iori");
var marin = new VipUser("Marin"); _chatRoom.Attach(juice);
_chatRoom.Attach(cola);
_chatRoom.Attach(iori);
_chatRoom.Attach(marin); _chatRoom.Talk2All(juice, "Hello Every one!");
_chatRoom.Talk2User(cola, iori, "Hello Iori!");
_chatRoom.Talk2User(iori, marin, "Hello Marin!"); Console.ReadKey();
} }

以上是调用方的代码演示,以下是这个案例的输出结果:

Cola recieved a group message from Juice,
(s)he says:Hello Every one!
Iori[VIP] recieved a group message from Juice,
(s)he says:Hello Every one!
Marin[VIP] recieved a group message from Juice,
(s)he says:Hello Every one!
------------------------------------------------------
Iori[VIP] recieved a private message from Cola,
(s)he says:Hello Iori!
------------------------------------------------------
Marin[VIP] recieved a private message from Iori[VIP],
(s)he says:Hello Marin!
------------------------------------------------------

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/419 访问。

1、降低了类的复杂度,将一对多转化成了一对一;

2、各个类之间的解耦,符合迪米特法则。

缺点:

1、中介者角色承担了较多的责任,所以一旦这个中介者对象出现了问题,整个系统将会受到重大的影响。

使用场景:

1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象;

2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

C#设计模式之17-中介者模式的更多相关文章

  1. Java设计模式(17)解释器模式(Interpreter模式)

    Interpreter定义:定义语言的文法,并且建立一个解释器来解释该语言中的句子. Interpreter似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个 ...

  2. 【转】设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

    设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据"单一职责原则",我们应该尽量将对象细化,使其只负责或呈现单一的职 ...

  3. 设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

    设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各 ...

  4. Java设计模式学习记录-中介者模式

    前言 中介者模式听名字就能想到也是一种为了解决耦合度的设计模式,其实中介者模式在结构上与观察者.命令模式十分相像:而应用目的又与结构模式“门面模式”有些相似.但区别于命令模式的是大多数中介者角色对于客 ...

  5. [设计模式] 17 中介者模式 Mediator Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对中介者模式是这样说的:用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变 ...

  6. C#设计模式学习笔记:(17)中介者模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7966240.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第五个模式--中 ...

  7. 设计模式学习之中介者模式(Mediator,行为型模式)(18)

    转载地址:http://www.cnblogs.com/zhili/p/MediatorPattern.html 一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信 ...

  8. C#设计模式之十七中介者模式(Mediator Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第五个模式,该模式是[中介者模式],英文名称是:Mediator Pattern.还是老套路,先从名字上来看看.“中介者模式”我第一次看到这个名称,我的理解 ...

  9. 17中介者模式Mediator

    一.什么是中介者模式 Mediator模式也叫中介者模式,是由GoF提出的23种 软件设计模式的一种.Mediator模式是行为模式之一, 在Mediator模式中,类之间的交互行为被统一放在 Med ...

  10. 大话设计模式Python实现-中介者模式

    中介者模式(Mediator Pattern):用一个对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互. 下面是一个中介者模式的demo ...

随机推荐

  1. It is indirectly referenced from required .class files错误查找的解决办法如下

    It is indirectly referenced from required .class files 原因:是JDK引入有问题导致的 解决方案:我之前是错误的引入成了JRE 坑哇!!!,改成如 ...

  2. mdk/iar汇编区别

    在代码移植中,经常遇到iar的代码转换问题,在此不间断记录一些,个人感觉还是IAR的更接近C一些,备查: 1. #ifdef的使用 // IAR #ifdef MACRO_XX #endif // M ...

  3. Ordinary - 官方原版软件下载站

    官网:http://a-1.vip/exe/

  4. 数字孪生,数据驱动下的北京 CBD 智能楼宇三维可视化系统

    前言 楼宇作为建筑基础设施的主体,为人们提供着重要的生存空间.随着物联网.人工智能概念的兴起以及智慧城市如火如荼的开展,智能楼宇的重要性越发突显. 随着城市现代化建设的发展,建筑的智能化,特别是公用建 ...

  5. Linux/Docker 中使用 System.Drawing.Common 踩坑小计

    前言 在项目迁移到 .net core 上面后,我们可以使用 System.Drawing.Common 组件来操作 Image,Bitmap 类型,实现生成验证码.二维码,图片操作等功能.Syste ...

  6. Python快速入门PDF高清完整版免费下载|百度云盘

    百度云盘:Python快速入门PDF高清完整版免费下载 提取码:w5y8 内容简介 这是一本Python快速入门书,基于Python 3.6编写.本书分为4部分,第一部分讲解Python的基础知识,对 ...

  7. Java基础篇(03):流程控制语句,和算法应用

    本文源码:GitHub·点这里 || GitEE·点这里 一.分支语句 流程控制语句对任何一门编程语言都是非常重要的,Java中基于流程控制程序执行的不同步骤和代码块. 1.IF条件 IF条件语句会根 ...

  8. Android中Activity的启动模式和使用场景

    一.为什么需要启动模式 在Android开发中,我们都知道,在默认的情况下,如果我们启动的是同一个Activity的话,系统会创建多个实例并把它们一一放入任务栈中.当我们点击返回(back)键,这些A ...

  9. PHP array_shift() 函数

    实例 删除数组中的第一个元素(red),并返回被删除的元素: <?php $a=array("a"=>"red","b"=> ...

  10. PHP timezone_version_get() 函数

    ------------恢复内容开始------------ 实例 返回时区数据库的版本: <?phpecho timezone_version_get();?> 运行实例 » 定义和用法 ...