浅谈设计模式 - 中介者模式(十六)

简介: 浅谈设计模式 - 中介者模式(十六)

前言


中介者模式是一种行为设计模式, 他的目的和门面模式类似,他负责的是将所有的底层交互细节隐藏,提供统一的对外接口供外部调用。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。


优缺点:



优点: 1、将对象的交互模式由多对一变为一对一。 2、可以实现多个类之间的强耦合。 3、此设计模式十分符合迪米特原则。

迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话

**缺点:**中介者对象会逐渐庞大,如果组件过多会变得复杂难以维护。


使用场景


1、在系统内部的对象之间通信紊乱的时候,按照设计模式单一职责的原则,通常会使用三方对象负责“请求”的转发,而中介的作用就是再次之上一个扩展,可以实现多个类之间的互相通信变为一对一的通信模式。

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

3、如果多个用户之间存在复杂的通信和耦合的情况时候,对外使用外观模式,对内则可以使用中介者模式。

**注意事项:**不应当在职责混乱的时候使用。


结构图



下面是中介者模式的结构图,这里构建了多个具体的实现对象,他们需要实现统一的通信就需要


网络异常,图片无法展示
|


和门面模式的对比


下面是门面模式的结构图,门面模式也叫做外观模式,可以看到和中介者的对象还有一定的相似性,外观提供,这两个模式的区别是外观主要提供对象的一致对外的接口,而中介模式实现的是让对象之间的通信由多对一变为一对一,我们简单的认为,中介者主要针对的对内多个复杂对象的统一,外观针对对外多个对象的方法统一。


网络异常,图片无法展示
|


实际案例


下面我们用一段简短的代码快速介绍一下这个设计模式的代码, 其实从上面结构图基本可以快速的写出模板代码,下面按照一个租房的案例进行快速的讲解:

首先是中介者的接口,中介者的接口需要由需要进行通信的子类实现,这里定义了租房的联络接口


public abstract class Mediator {
    //申明一个联络方法
    public abstract void constact(String message,Person person);
}


用户类,内部嵌入了联络的对象,使得子类可以和任意对象进行通信


public abstract class Person {
    protected String name;
    protected Mediator mediator;
    Person(String name,Mediator mediator){
        this.name = name;
        this.mediator = mediator;
    }
}


房东类,继承Person类的同时,实现自己的通信方法


public class HouseOwner extends Person{
    HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }
    /**
     * @desc 与中介者联系
     * @param message
     * @return void
     */
    public void constact(String message){
        mediator.constact(message, this);
    }
    /**
     * @desc 获取信息
     * @param message
     * @return void
     */
    public void getMessage(String message){
        System.out.println("房主:" + name +",获得信息:" + message);
    }
}


下面是另一个Person类,也就是中介者的对象,负责和房东进行通信


public class Tenant extends Person{
    Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }
    /**
     * @desc 与中介者联系
     * @param message
     * @return void
     */
    public void constact(String message){
        mediator.constact(message, this);
    }
    /**
     * @desc 获取信息
     * @param message
     * @return void
     */
    public void getMessage(String message){
        System.out.println("租房者:" + name +",获得信息:" + message);
    }
}


下面是具体的中介对象,可以看到下面定义了房东的的信息以及租房者的对象,通过中介对象,我们实现了房东和房客之间的通信,让他们统一通过中介机构进行通信。


public class MediatorStructure extends Mediator{
    //首先中介结构必须知道所有房主和租房者的信息
    private HouseOwner houseOwner;
    private Tenant tenant;
    public HouseOwner getHouseOwner() {
        return houseOwner;
    }
    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }
    public Tenant getTenant() {
        return tenant;
    }
    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }
    public void constact(String message, Person person) {
        if(person == houseOwner){          //如果是房主,则租房者获得信息
            tenant.getMessage(message);
        }
        else{       //反正则是房主获得信息
            houseOwner.getMessage(message);
        }
    }
}


最后是客户端的代码,可以看到通过中介的形式,可以实现中介和房东一对一,以及租房者和中介一对一的解耦合的形式.


public class Client {
    public static void main(String[] args) {
        //一个房主、一个租房者、一个中介机构
        MediatorStructure mediator = new MediatorStructure();
        //房主和租房者只需要知道中介机构即可
        HouseOwner houseOwner = new HouseOwner("张三", mediator);
        Tenant tenant = new Tenant("李四", mediator);
        //中介结构要知道房主和租房者
        mediator.setHouseOwner(houseOwner);
        mediator.setTenant(tenant);
        tenant.constact("听说你那里有三室的房主出租.....");
        houseOwner.constact("是的!请问你需要租吗?");
    }
}


总结



  1. 由于中介者需要将多个对象的行为进行连接通信,虽然各个对象的改动会改变通信的细节,但是中介者的改动却会影响整体通信行为,这是一把双刃剑,既让对象的通信简化同时,也让复杂耦合到了一处。这时候可以结合策略或者工厂将中介的通信行为实现动态的扩展
  2. 在中介者模式中通过引用中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少。
  3. 中介的行为类似一种对象的闭包和统一通信,中介者模式按照房东,中介,房客的理解可以快速的了解到这个结构
  4. 其实我们可以把MVC看作一种中介的变种,Service层起到了承接的作用。


写在最后



中介的行为经常在使用,但是使用中介者模式需要小心的考虑类的耦合和中介者类是否会变得复杂或者难以维护。

相关文章
|
3月前
|
Ubuntu 安全 数据挖掘
揭开Linux系统神秘面纱,选择Centos、Debian、Ubuntu?
CentOS、Debian 和 Ubuntu 三种 Linux 操作系统各具优势和适用场景。CentOS 更适合用于服务器应用,Debian 更适合稳定需求的系统环境,而 Ubuntu 更适合用于桌面操作系统和开发环境等。CentOS 和 Debian 相对保守,重视稳定性和安全性;Ubuntu 侧重更新和更好的可用性,重视用户体验。此外, Ubuntu 在市场上的占有率最高。因此,选择适合自己需求的操作系统非常重要,可以帮助用户提高效率和使用体验。
|
存储 测试技术
ECCV 2024:比基准高30%,媲美Gemini 1.5 Pro,基于记忆的视频理解智能体来了
在ECCV 2024会议上,一篇题为“VideoAgent: A Memory-augmented Multimodal Agent for Video Understanding”的论文备受关注。该论文提出了一种结合大型语言模型和视觉-语言模型的新型智能体VideoAgent,通过创新的统一记忆机制,构建结构化记忆系统,实现对长视频中时间关系的理解。VideoAgent利用视频片段定位、物体记忆等多种工具进行交互式任务处理,在NExT-QA和EgoSchema等基准测试中表现出色,分别提升了6.6%和26.0%的成绩,但其记忆系统和交互方法仍有待优化。
292 1
|
弹性计算 开发框架 .NET
阿里云服务器和虚拟主机有什么区别?多维度对比
阿里云虚拟主机便于快速建站,适合初学者,预装常用环境如PHP、ASP等,操作简易。云服务器ECS则提供全面权限与弹性扩展能力,不仅限于建站,亦可用于APP、游戏等场景,更适合技术娴熟的用户。尽管虚拟主机价格较低,但鉴于云服务器性能优越且价格持续下降,推荐选择云服务器以获取更佳性价比与广泛的应用场景。
456 3
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
3745 5
|
供应链 安全 物联网
区块链技术的应用场景和优势
区块链技术的应用场景和优势
1389 0
Python 的 __name__ 变量及其应用
__name__ 是 Python 中的一个特殊变量,它代表当前模块的名字。 当一个 Python 文件被直接运行的时候,__name__ 的值会被设置为 __main__。 当代码被导入到其他模块中运行时,__name__ 的值会被设置为模块名称。
9款鼠标划入卡片特效
在线演示 本地下载
804 0
|
Web App开发 缓存 应用服务中间件