设计模式 | 中介者模式(详解)

中介者模式

案例介绍:

编写信息管理模块:

界面组件之间存在较为复杂的交互关系:如果删除一个客户,要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名称也将减少一个;如果增加一个客户信息,客户列表中需增加一个客户,且组合框中也将增加一项。
如果实现界面组件之间的交互一个问题?

(1) 当用户单击“增加”按钮、“删除”按钮、“修改”按钮或“查询”按钮时,界面左侧的“客户选择组合框”、“客户列表”以及界面中的文本框将产生响应。

(2) 当用户通过“客户选择组合框”选中某个客户姓名时,“客户列表”和文本框将产生响应。

(3) 当用户通过“客户列表”选中某个客户姓名时,“客户选择组合框”和文本框将产生响应。

于是开发人员根据组件之间的交互关系绘制了如图20-3所示初始类图:
在这里插入图片描述

设计方案存在如下问题:
(1) 系统结构复杂且耦合度高:每一个界面组件都与多个其他组件之间产生相互关联和调用,若一个界面组件对象发生变化,需要跟踪与之有关联的其他所有组件并进行处理,系统组件之间呈现一种较为复杂的网状结构,组件之间的耦合度高。

(2) 组件的可重用性差:由于每一个组件和其他组件之间都具有很强的关联,若没有其他组件的支持,一个组件很难被另一个系统或模块重用,这些组件表现出来更像一个不可分割的整体,而在实际使用时,我们往往需要每一个组件都能够单独重用,而不是重用一个由多个组件组成的复杂结构。

(3) 系统的可扩展性差:如果在上述系统中增加一个新的组件类,则必须修改与之交互的其他组件类的源代码,将导致多个类的源代码需要修改,同样,如果要删除一个组件也存在类似的问题,这违反了“开闭原则”,可扩展性和灵活性欠佳。

由于存在上述问题,Sunny公司开发人员不得不对原有系统进行重构,那如何重构呢?大家想到了“迪米特法则”,引入一个“第三者”来降低现有系统中类之间的耦合度。由这个“第三者”来封装并协调原有组件两两之间复杂的引用关系,使之成为一个松耦合的系统,这个“第三者”又称为“中介者”,中介者模式因此而得名。

你中有我,我中有你,不利于松耦合

中介者模式基本介绍

  1. 中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互。
    中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立
    地改变它们之间的交互
  2. 中介者模式属于行为型模式,使代码易于维护
  3. 比如MVC模式,C(Controller控制器)是M(Model模型)和V(View视图)的中介者,在前后端交互时起到了中间人的作用

对象之间存在大量的多对多联系,将导致系统非常复杂,这些对象既会影响别的对象,也会被别的对象所影响,这些对象称为同事对象,它们之间通过彼此的相互作用实现系统的行为。在网状结构中,几乎每个对象都需要与其他对象发生相互作用,而这种相互作用表现为一个对象与另外一个对象的直接耦合,这将导致一个过度耦合的系统

中介者模式是“迪米特法则”的一个典型应用。

中介者模式类图:

在这里插入图片描述

中介者模式角色:

Mediator(抽象中介者):它定义一个接口,该接口用于与各同事对象之间进行通信。

ConcreteMediator(具体中介者):它是抽象中介者的子类,通过协调各个同事对象来实现协作行为,它维持了对各个同事对象的引用。

Colleague(抽象同事类):它定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。

ConcreteColleague(具体同事类):它是抽象同事类的子类;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。

中介者类承担了两方面的职责:

(1) 中转作用(结构性):通过中介者提供的中转作用,各个同事对象就不再需要显式引用其他同事,当需要和其他同事进行通信时,可通过中介者来实现间接调用。该中转作用属于中介者在结构上的支持。

(2) 协调作用(行为性):中介者可以更进一步的对同事之间的关系进行封装,同事可以一致的和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对同事的请求进行进一步处理,将同事成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持。

代码实现:

抽象组件类;抽象同事类

`
public abstract class Component {
    protected  Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
    public void changed (){
    mediator.componentChanged(this);
    }
    public abstract void update();
}

具体同事类: 按钮组件

/**
 * @author 孙一鸣 on 2020/2/20
 */
public class MyButton extends Component{
    @Override
    public void update() {
    //按钮不产生交互
    }
}

具体同事类:组合框类

/**
 * 组合框类:具体同事类
 * @author 孙一鸣 on 2020/2/20
 */
public class MyComboBox extends Component {


    public void update() {
        System.out.println("组合框增加一项:比尔盖茨。");
    }

    public void select() {
        System.out.println("组合框选中项:马云");

    }
}

具体同事类:列表框类

/**
 * 列表框类:具体同事类
 * @author 孙一鸣 on 2020/2/20
 */
public class MyList extends  Component{
    @Override
    public void update() {
        System.out.println("列表框新加同事:比尔盖茨");
    }

    public void select (){
        System.out.println("列表框选中项:马云");
    }
}

具体同事类:文本框类

/**
 * //文本框类:具体同事类
 *
 * @author 孙一鸣 on 2020/2/20
 */
public class MyTextBox extends Component {
    public void update() {
        System.out.println("客户信息增加成功后文本框清空。");
    }

    public void setText() {
        System.out.println("文本框显示:马云");

    }
}

抽象中介者类:


/**
 *
 //抽象中介者
 * @author 孙一鸣 on 2020/2/20
 */
public abstract class Mediator {
    public  abstract  void componentChanged(Component c);
}

具体中介者类:


/**
 * 具体中介者
 *
 * @author 孙一鸣 on 2020/2/20
 */
public class ConcreteMediator extends Mediator{
    //维持对多个同事对象的引用
    public MyButton addButton;
    public MyList list;
    public MyTextBox userNameTextBox;
    public MyComboBox cb;


    //封装同事对象之间的交互

    @Override
    public void componentChanged(Component c) {
        //单击按钮
        if(c == addButton) {
            System.out.println("--单击增加按钮--");
            list.update();
            cb.update();
            userNameTextBox.update();
        }
        //从列表框选择客户
        else if(c == list) {
            System.out.println("--从列表框选择客户--");
            cb.select();
            userNameTextBox.setText();
        }
        //从组合框选择客户
        else if(c == cb) {
            System.out.println("--从组合框选择客户--");
            cb.select();
            userNameTextBox.setText();
        }

    }
}

测试类:


/**
 * @author 孙一鸣 on 2020/2/20
 */
public class Client {
    public static void main(String args[]) {
        //定义中介者对象
        ConcreteMediator mediator;
        mediator = new ConcreteMediator();

        //定义同事对象
        MyButton addBT = new MyButton();
        MyList list = new MyList();
        MyComboBox cb = new MyComboBox();
        MyTextBox userNameTB = new MyTextBox();

        addBT.setMediator(mediator);
        list.setMediator(mediator);
        cb.setMediator(mediator);
        userNameTB.setMediator(mediator);

        mediator.addButton = addBT;
        mediator.list = list;
        mediator.cb = cb;
        mediator.userNameTextBox = userNameTB;

        addBT.changed();
        System.out.println("-----------------------------");
        list.changed();

    }
}

结果截图:

在这里插入图片描述

中介者模式的注意事项和细节

  1. 多个类相互耦合,会形成网状结构, 使用中介者模式将网状结构分离星型结构,进行解耦
  2. 减少类间依赖,降低了耦合,符合迪米特原则
  3. 中介者承担了较多的责任,一旦中介者出现了问题,整个系统就会受到影响
  4. 如果设计不当,中介者对象本身变得过于复杂,这点在实际使用时,要特别注意

本文参考链接:https://blog.csdn.net/lovelion/article/details/8483081
版权声明:本文为CSDN博主「LoveLion」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值