美文网首页JavaEE 学习专题程序员
Java设计模式之-中介者模式(Mediator)

Java设计模式之-中介者模式(Mediator)

作者: Mock2052 | 来源:发表于2017-11-28 01:04 被阅读0次

    中介者模式,又叫调停者模式。我看的书里面是叫做调停者的,我个人认为没有“中介者”这个名字容易理解。

    中介者模式:在一个庞大系统中,多个类之间需要进行信息的交换,从而引发后续的行为。这个时候为了避免类之间呈网状关联,引入一个中介者用以管理其他类,接收某些类传入的信息,并反映在对应的相应类上,变网状为星状,减少类之间的耦合性。

    以上是我对中介者模式的理解,下面我们来看一下在Java语言中,该模式应该如何设计:


    中介者模式
    • Mediator:中介者,实际上可以作为一个抽象类或接口,用以定义一个中介者需要实现的方法,如记录变更、响应变更、增减Colleague等;
    • ConcreteMediator:具体中介者,实现了中介者的方法,明确应该如何进行各项操作;
    • Colleague:协同者,一般是一个抽象类或接口,能够返回一个Mediator对象;
    • ConcreteColleague:具体协同者,实现了Colleague的方法,并且根据实际情况与Mediator进行交互;

    中介者

    很简单的一个接口,定义了一个用于反馈的方法:

    package com.designpattern;
    
    public interface IMediator {
        public void react(AbstractColleague c);
    }
    
    

    协同者

    包含一个中介者的实例,为了能够定义构造函数,我将它写成了一个抽象类。请注意,接口不能定义构造函数

    package com.designpattern;
    
    public abstract class AbstractColleague {
        protected IMediator mediator;
    
        public AbstractColleague(IMediator m) {
            mediator = m;
        }
    
        public final IMediator getMediator() {
            return mediator;
        }
    }
    

    具体协同者

    我们先来定义两个具体的协同者,他们直接需要进行某些交互的动作,但是由于中介者的存在,他们不必互相了解,只要将自身的变化告诉中介者即可。

    ViewColleague
    package com.designpattern;
    
    public class ViewColleague extends AbstractColleague {
        public ViewColleague(IMediator m) {
            super(m);
        }
    
        public void mockClick() {
            System.out.println("View got a click action.");
            getMediator().react(this);
        }
    
        public void display(String data) {
            System.out.println("View got " + data + " from model.");
        }
    
        public void prepareShutdown(){
            System.out.println("View knows that: Model gonna shutdown, backup your data.");
        }
    }
    
    ModelColleague
    package com.designpattern;
    
    public class ModelColleague extends AbstractColleague {
    
        public ModelColleague(IMediator m) {
            super(m);
        }
    
        public String whenClick(){
            System.out.println("Model should return some data to view.");
            return "data";
        }
    
        public void shutdown(){
            System.out.println("Model will shutdown in 5 sec.");
            getMediator().react(this);
        }
    }
    

    具体中介者

    其实看到我上面两个类的命名之后,大家应该就能猜到我在干什么。我想用中介者模式表现MVC架构,或者也能说我想用MVC来说明中介者模式的作用。

    package com.designpattern;
    
    public class ControllerMediator implements IMediator {
        private ViewColleague viewColleague;
        private ModelColleague modelColleague;
    
        public ControllerMediator setView(ViewColleague v){
            viewColleague = v;
            return this;
        }
    
        public ControllerMediator setModel(ModelColleague m){
            modelColleague = m;
            return this;
        }
    
        @Override
        public void react(AbstractColleague c) {
            if (c instanceof ViewColleague) {
                String data = modelColleague.whenClick();
                viewColleague.display(data);
            } else if (c instanceof ModelColleague) {
                viewColleague.prepareShutdown();
            } else {
                System.out.println("Not Supported Class: " + c.getClass().getName());
                // you can also :
                //throw new NotSupportedException();
            }
        }
    }
    

    大家可以看到,在中介者中保存了两个Colleague对象,如果说我们现在展示的不是MVC,而是MVVM框架,那么就会有更多的实例保存在终结者中。这个是无法避免的,中介者必须拥有所有的协同者

    好的,然后我们来写一个main方法驱动整个代码:

    public static void main(String[] args){
            ControllerMediator controller = new ControllerMediator();
            ViewColleague view = new ViewColleague(controller);
            ModelColleague model = new ModelColleague(controller);
            controller.setView(view).setModel(model);
    
            //view change:
            view.mockClick();
    
            //model change:
            model.shutdown();
        }
    

    我们先将协同者和中介者进行关联,然后尝试模拟View的变更以及Model的变更。执行main方法,可以看到输出结果如下:

    View got a click action.
    Model should return some data to view.
    View got data from model.
    Model will shutdown in 5 sec.
    View knows that: Model gonna shutdown, backup your data.
    

    View出现了状态的改变,但它不需要知道有谁需要因此而做什么事情,只需要告诉中介者即可,Model亦然。两者存在着数据和信息的交换,但是又不知道彼此,一个中介者将两者完美地解耦了。

    中介者模式和观察者模式

    其实在思考和编写这个例子的时候,我一直在想这两个模式的关系。两者虽然很相似,但是理解之后还是能发现有很大区别的:

    1. 观察者模式中,变更发生在被观察者,即中心节点;中介者模式中,变更发生在某一个协同类,而非中心节点-中介类;
    2. 观察者模式中,针对变更的行为由观察者实现;中介者模式中,虽然会使用到协同类的某些方法,但是具体行为顺序和参数则由中介者来确定;
    3. 观察者模式中,由于观察者实现了同一接口,在被观察者看来是一组相同的对象;在中介者模式中,每个协同类虽然一般都会源自某个类或接口,但实际上各司其职,是不同的对象,有着自身独特的方法;
    4. 观察者模式中,观察者的增加不会影响被观察者的行为;中介者模式中,协同类的增加,势必会影响中介者的行为;

    以上四点,是我自己能想到的一些区别,其中关于第四点我想多说一点,其实它也就是中介者模式存在的弊端。

    牺牲小我,完成大我

    中介者模式能够让协同类之间的耦合性消失,但又引出了新的问题:它自己。由于集所有协同类与一身,并且负责担当类之间的调度员和粘合剂,使得中介者自身改动频繁,且难于维护。降低了系统耦合,却将所有复杂度和内聚性融于自身。

    因此,合理选择中介者的使用场景和使用粒度非常重要,不需要为了使用设计模式而使用。要让中介者的牺牲是值得的才行。

    相关文章

      网友评论

        本文标题:Java设计模式之-中介者模式(Mediator)

        本文链接:https://www.haomeiwen.com/subject/etwjbxtx.html