C#设计模式之17-中介者模式
中介者模式(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-中介者模式的更多相关文章
- Java设计模式(17)解释器模式(Interpreter模式)
Interpreter定义:定义语言的文法,并且建立一个解释器来解释该语言中的句子. Interpreter似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个 ...
- 【转】设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)
设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据"单一职责原则",我们应该尽量将对象细化,使其只负责或呈现单一的职 ...
- 设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)
设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各 ...
- Java设计模式学习记录-中介者模式
前言 中介者模式听名字就能想到也是一种为了解决耦合度的设计模式,其实中介者模式在结构上与观察者.命令模式十分相像:而应用目的又与结构模式“门面模式”有些相似.但区别于命令模式的是大多数中介者角色对于客 ...
- [设计模式] 17 中介者模式 Mediator Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对中介者模式是这样说的:用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变 ...
- C#设计模式学习笔记:(17)中介者模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7966240.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第五个模式--中 ...
- 设计模式学习之中介者模式(Mediator,行为型模式)(18)
转载地址:http://www.cnblogs.com/zhili/p/MediatorPattern.html 一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信 ...
- C#设计模式之十七中介者模式(Mediator Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第五个模式,该模式是[中介者模式],英文名称是:Mediator Pattern.还是老套路,先从名字上来看看.“中介者模式”我第一次看到这个名称,我的理解 ...
- 17中介者模式Mediator
一.什么是中介者模式 Mediator模式也叫中介者模式,是由GoF提出的23种 软件设计模式的一种.Mediator模式是行为模式之一, 在Mediator模式中,类之间的交互行为被统一放在 Med ...
- 大话设计模式Python实现-中介者模式
中介者模式(Mediator Pattern):用一个对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互. 下面是一个中介者模式的demo ...
随机推荐
- MySQL主从复制--单库复制搭建
背景说明 负责公司MySQL数仓的搭建和维护,因为前端业务涉及到一次业务表的分库,导致整个平台新增加一台MySQL服务器,需要将该库数据通过主从复制同步至原有的数仓实例. 数据流向说明如下图: 业务环 ...
- Ethical Hacking - GAINING ACCESS(1)
Gaining Access Introduction Everything is a computer Two main approaches (1)Server Side Do not requi ...
- echarts 实战 : 标题的富文本样式
官方文档在这一块交待的不是很清楚,记录一下. title:{ left:15, top:10, subtext:"AAA {yellow|316} BBB {blue|219}", ...
- DJANGO-天天生鲜项目从0到1-005-FastDFS与Nginx打造自定义文件存储系统
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- 黎曼函数ζ(2n)的几种求法
\(\zeta (2n)\)的几种求法 目录 $\zeta (2n)$的几种求法 结论 欧拉的证明 进一步探索,$\zeta$ 函数.余切.伯努利数的关系 傅立叶分析证明 留数法证明 参考资料 结论 ...
- 全栈的自我修养: 0005 Java 包扫描实现和应用(Jar篇)
全栈的自我修养: 0005 Java 包扫描实现和应用(Jar篇) It's not the altitude, it's the attitude. 决定一切的不是高度而是态度. Table of ...
- VMware虚拟机黑屏解决
1.管理员身份运行cmd(右键->以管理员身份运行) 2.修复LSP,输入以下命令然后回车 netsh winsock reset 3.重启电脑即可
- Redis 和 memcache 简单比较
1.Redis不仅仅支持简单的key-value类型的数据,同时还提供list.set.zset.hash等数据结构的存储. 2.Redis支持master-slave(主--从)模式应用. 3.Re ...
- 让表单input等文本框为只读不可编辑的方法-转
有时候,我们希望表单中的文本框是只读的,让用户不能修改其中的信息,如使<input type="text" name="input1" value=&qu ...
- ken桑带你读源码 之scrapy pipelines\images.py
大家先看看 http://www.cnblogs.com/attitudeY/p/7078559.html 下面我做一些补充 最新版本1.1 已经支持 下载路径保存到 item 48行 ...