在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。例如,每个人必须记住他(她)所有朋友的电话;而且,朋友中如果有人的电话修改了,他(她)必须告诉其他所有的朋友修改,这叫作“牵一发而动全身”,非常复杂。

如果把这种“网状结构”改为“星形结构”的话,将大大降低它们之间的“耦合性”,这时只要找一个“中介者”就可以了。如前面所说的“每个人必须记住所有朋友电话”的问题,只要在网上建立一个每个朋友都可以访问的“通信录”就解决了。这样的例子还有很多,例如,你刚刚参力口工作想租房,可以找“房屋中介”;或者,自己刚刚到一个陌生城市找工作,可以找“人才交流中心”帮忙。

在软件的开发过程中,这样的例子也很多,例如,在 MVC 框架中,控制器(C)就是模型(M)和视图(V)的中介者;还有大家常用的 QQ 聊天程序的“中介者”是 QQ 服务器。所有这些,都可以采用“中介者模式”来实现,它将大大降低对象之间的耦合性,提高系统的灵活性。

中介者模式的适用场景

一般在以下情况下可以考虑使用中介者模式:

  1. 一组定义良好的对象,现在要进行复杂的相互通信。
  2. 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

模式的定义与特点

中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

中介者模式是一种对象行为型模式,其主要优点如下。

  1. 降低了对象之间的耦合性,使得对象易于独立地被复用。
  2. 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。

其主要缺点是:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

广义中介者

在实际开发中,经常会简化中介者模式,来是开发变得简单,比如有如下的简化。

  1. 通常会去掉同事对象的父类,这样可以让任意的对象,只需要有交互,就可以成为同事
  2. 通常不定义Mediator接口,把具体的中介者对象实现成为单例
  3. 同事对象不再持有中介者,而是在需要的时候直接获取中介者对象并调用;中介者也不再持有同事对象,而是在具体处理方法里面去创建,或获取,或从数据传入需要的同事对象。

经过这样的简化、变形的情况称为广义中介者。

简而概之(伪代码演示)

中介者模式就是通过一个中介者,来让多个交错纵横的引用的类相互解耦,通过访问中介者类的方法就可以访问其他类的方法,每个类之间是相互平等的。比如下面的代码,我们有一个学生类,一个教师类,我们在控制器中有两个Action来处理这两个类的新增,那我们的实现应该是如下的:

public class Student{//属性...}
public class Teacher{//属性...}

服务类

public class StudentService
{
  public void Add(Student entity){//添加方法}
}
public class TeacherService
{
  public void Add(Teacher entity){//添加方法}
}

控制器的实现,可以看到有多个服务类被实例化。

public class AddController : Controller
{
  StudentService studentService = new StudentService();
  TeacherService teacherService = new TeacherService();
  public IActionResult Student(Student entity)
  {
    studentService.Add(entity);
    return Content("添加成功");
  }
  public IActionResult Teacher(Teacher entity)
  {
    teacherService.Add(entity);
    return Content("添加成功");
  }
}

如果我们用了中介者模式,那就可以免去这些服务类的实例化,直接使用中介者类执行对应的添加方法就行了,下面就进行简单的实现。

中介者模式的简单实现

下面只是通过简单的例子来体现中介者模式的思想,不用过于纠结是否合理,我们可以在实际项目中按自己的需求来实现,就想上面描述的广义的中介者模式。

学生类和教师类以及对应的服务类

public class Base{}
public class Student : Base{//属性...}
public class Teacher : Base{//属性...}
public class StudentService
{
public string Add(Student entity){return "已添加学生";}
}
public class TeacherService
{
public string Add(Teacher entity){return "已添加教师";}
}

中介者类

public interface IMediator{string Add(Base entity);}
public class Mediator : IMediator
{
private StudentService studentService = new StudentService();
private TeacherService teacherService = new TeacherService();
public string Add(Base entity)
{
if(entity is Student)
return studentService.Add((Student)entity);
else if (entity is Teacher)
return teacherService.Add((Teacher)entity);
return "添加失败";
}
}

控制器中使用中介者类

public class AddController : Controller
{
private IMediator iMediator = new Mediator();
public IActionResult Student(Student entity)
{
return Content(iMediator.Add(entity));
}
public IActionResult Teacher(Teacher entity)
{
return Content(iMediator.Add(entity));
}
}

访问学生新增接口就会出现如下结果:

在NetCore中使用MediatR实现中介者模式

通过 .NET CORE 自带的 IoC 注入

引用 MediatR nuget:install-package MediatR

引用IOC扩展 nuget:installpackage MediatR.Extensions.Microsoft.DependencyInjection //扩展包

在Startup类中的ConfigureServices方法中注册MediatR服务,下面这句话可以扫描继承IRequestHandler接口的实现对象并添加到IOC的容器中

services.AddMediatR(typeof(Startup).GetTypeInfo().Assembly);

为我们的学生类和教师类继承IRequest接口,表示该对象是处理器的一个对象。

public class Student : IRequest<string>{//属性...}
public class Teacher : IRequest<string>{//属性...}

为我们的服务类添加IRequestHandler接口创建处理器对象。

public class StudentService : IRequestHandler<Student,string>
{
public Task<string> Handle(Student entity, CancellationToken cancellationToken)
{
return Task.FromResult("已添加学生");
}
}
public class TeacherService : IRequestHandler<Teacher, string>
{
public Task<string> Handle(Teacher entity, CancellationToken cancellationToken)
{
return Task.FromResult("已添加教师");
}
}

在控制器中使用,通过调用中介者的Send方法,自动匹配对应使用该处理器对象的处理器方法。

public class AddController : Controller
{
private readonly IMediator _mediator; public AddController(IMediator mediator)
{
_mediator = mediator;
}
public IActionResult Student(Student entity)
{
return Content(_mediator.Send(entity).Result);
}
public IActionResult Teacher(Teacher entity)
{
return Content(_mediator.Send(entity).Result);
}
}

这样我们的改造就完成了。继承IRequest接口有一个泛型表示处理器返回参数类型,与IRequestHandler接口的第二个参数和IRequestHandler接口定义的方法Handle方法的返回值对应,可以不定义表示返回void。IRequestHandler接口的第一个参数必须为继承IRequest接口的类。

中介者模式及在NetCore中的使用MediatR来实现的更多相关文章

  1. C#设计模式-中介者模式

    在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信平台,这些都是中介者模式在现实生活中的应用,下面就具体分享下我对中介者模式的理解. 一. 中介者(Mediator)模式 从 ...

  2. (七)中介者模式-C++实现

    用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显示地相互引用,从而使其解耦合松散而且可以独立地改变他们之间的交互. 中介者模式适合于 系统中不希望对象之间直接交互,即不希望类之间相互包含, ...

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

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

  4. C#设计模式(18)——中介者模式(Mediator Pattern)

    一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信平台,这些都是中介者模式在现实生活中的应用,下面就具体分享下我对中介者模式的理解. 二. 中介者模式的介绍 2.1 ...

  5. 大熊君说说JS与设计模式之------中介者模式Mediator

    一,总体概要 1,笔者浅谈 我们从日常的生活中打个简单的比方,我们去房屋中介租房,房屋中介人在租房者和房东出租者之间形成一条中介.租房者并不关心他租谁的房.房东出租者也不关心他租给谁.因为有中介的存在 ...

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

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

  7. 设计模式 ( 十六 ): Mediator中介者模式 -- 行为型

    1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中. 对于一个模块或者系统,可能由很多对象构成,而且这些对象 ...

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

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

  9. 设计模式-中介者模式(Mediator)

    /***中介者模式在消息队列中的应用*/package test.mediator; public abstract class Message { private Messages messages ...

随机推荐

  1. 返回头添加cookie信息

    返回类型 HttpResponseMessage //构建返回对象 var res= Request.CreateResponse(HttpStstusCode.Ok,返回体) //创建cookie对 ...

  2. 【4】进大厂必须掌握的面试题-Java面试-jdbc

    1.什么是JDBC驱动程序? JDBC驱动程序是使Java应用程序与数据库进行交互的软件组件.JDBC驱动程序有4种类型: JDBC-ODBC桥驱动程序 本机API驱动程序(部分为Java驱动程序) ...

  3. 我不信这篇文章能让你学会C语言,但是我还是想分享一下!

    前言 C 语言是一门抽象的.面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首 ...

  4. monolog handler用哪个

    Handlers 记录日志到文件与系统日志(syslog) StreamHandler:记录日志到任何 PHP stream,用它来记录到文件. RotatingFileHandler: 每天一个文件 ...

  5. centos8平台使用xfs文件系统

    一,xfs文件系统的特点 XFS是一种高性能的日志文件系统, 它是由SGI公司设计的,被称为业界最先进的.最具可升级性的文件系统技术. 最初是从unix(irix)移植到linux系统上的. 从cen ...

  6. scrapy Request方法

    # -*- coding: utf-8 -*- import scrapy class TestSpider(scrapy.Spider): name = 'test' allowed_domains ...

  7. .net 连接数据库实例

    web.config配置 <appSettings> <add key="ConnectionString" value="server=.;datab ...

  8. vue多页面与单页面开发的区别。

    进入一家新的公司,要开发移动端app项目,前端技术选型时前端组长选的是vue的多页面开发,当时很蒙,vue不是单页面开发吗?咋出来多页面的.接触之后才发现确实存在也挺简单的,省去了路由表的配置.那就给 ...

  9. 2017年暑假ACM集训日志

    20170710: hdu1074,hdu1087,hdu1114,hdu1159,hdu1160,hdu1171,hdu1176,hdu1010,hdu1203 20170711: hdu1231, ...

  10. user.ini Operation not permitted

    rm: cannot remove '/public/.user.ini': Operation not permitted chattr -i .user.ini rm -f .user.ini