设计模式-中介模式

介绍

意图:

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

主要解决:

对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。

何时使用:

多个类相互耦合,形成了网状结构。

如何解决:

将上述网状结构分离为星型结构。

关键代码:

1.对象 Colleague 之间的通信封装到一个类中单独处理。
2.当各Colleague仅与一个Mediator一起工作时,没有必要定义一个抽象的Mediator类。
3.Colleague与Mediator通信,可以使用Observer模式,或者在Mediator中定义一个特殊的通知接口,各Colleague在通信时直接调用该接口。

应用实例:

1、中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。 2、机场调度系统。
3、MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。

优点:

1.减少了子类生成,用mediator将原本分布于多个对象间的行为集中在一起。改变这些行为只需生成Mediator的子类即可。这样各个Colleague类可被重用。
2、降低了类的复杂度,将一对多转化成了一对一,更加易于理解、维护和扩展。
3、各个Colleague类之间的解耦。
4、它对对象如何协作进行了抽象,使你将注意力从对象各自本身的行为转移到他们之间的交互上
5. 它使控制集中化,将交互的复杂性变为终结者的复杂性。

缺点:

中介者会庞大,变得复杂难以维护。

使用场景:

1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。
2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

注意事项:

不应当在职责混乱的时候使用。

UML

设计模式-中介模式_第1张图片

  • Mediator:中介者接口。在里面定义各个同事之间交互需要的方法,可以是公共的通讯方法,比如changed方法,大家都用,也可以是小范围的交互方法。
  • ConcreteMediator:具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。
  • Colleague:同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并实现一些具体同事类之间的公共功能,比如:每个具体同事类都应该知道中介者对象,也就是具体同事类都会持有中介者对象,就可以定义到这个类里面。
  • ConcreteColleague:具体的同事类,实现自己的业务,在需要与其它同事通讯的时候,就与持有的中介者通信,中介者会负责与其它的同事交互。

实例

抽象中介者角色
首先我们创建抽象中介者类,在这个例子中,它是一个武林联盟类,如下所示。

public abstract class WulinAlliance {
    public abstract void notice(String message, United united);
}

notice方法用于向门派发送通知,其中United为抽象同事类也就是门派类,接下来我们来创建它。

抽象同事角色

public abstract class United {
    protected WulinAlliance wulinAlliance;
    public United(WulinAlliance wulinAlliance){
        this.wulinAlliance=wulinAlliance;
    }
}

门派类(抽象同事类)会在构造方法中得到武林联盟类(抽象中介者类)。

具体同事角色
具体同事类包括武当派、峨眉派和少林派,如下所示。

/**
 * 具体同事类(武当)
 */

public class Wudang extends United {
    public Wudang(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message) {
        wulinAlliance.notice(message, this);
    }
    public void getNotice(String message) {
        System.out.println("武当收到消息:" + message);
    }
}

/**
 * 具体同事类(峨眉派)
 */
public class Emei extends United {
    public Emei(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message) {
        wulinAlliance.notice(message, Emei.this);
    }
    public void getNotice(String message) {
        System.out.println("峨眉收到消息:" + message);
    }
}

/**
 * 具体同事类(少林派)
 */
public class Shaolin extends United {
    public Shaolin(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message){
        wulinAlliance.notice(message,Shaolin.this);
    }
    public void getNotice(String message){
        System.out.println("少林收到消息:"+message);
    }
}

武当、峨眉和少林类都有两个方法,其中getNotice方法是自有方法,对于其他的门派(同事类)和武林联盟(中介者)没有依赖,只是用来接收武林盟主的通知。sendAlliance方法则是依赖方法,它必须通过武林盟主才能完成行为。

具体中介者角色
具体中介者类则是武林盟主类,如下所示

public class Champions extends WulinAlliance {
    private Wudang wudang;
    private Shaolin shaolin;
    private Emei emei;
    public void setWudang(Wudang wudang) {
        this.wudang = wudang;
    }
    public void setEmei(Emei emei) {
        this.emei = emei;
    }
    public void setShaolin(Shaolin shaolin) {
        this.shaolin = shaolin;
    }
    @Override
    public void notice(String message, United united) {
        if (united == wudang) {
            shaolin.getNotice(message);
        } else if (united == emei) {
            shaolin.getNotice(message);
        } else if (united == shaolin) {
            wudang.getNotice(message);
            emei.getNotice(message);
        }
    }
}

武林盟主需要了解所有的门派,所以需要用setter来持有武当、峨眉和少林的引用。notice方法会根据不同门派发来的消息,转而通知给其他的门派。比如武当发来的消息,武林盟主就会将消息通知给少林。

客户端调用

public class Client {
    public static void main(String[]args) {
        Champions champions=new Champions();
        Wudang wudang=new Wudang(champions);
        Shaolin shaolin=new Shaolin(champions);
        Emei emei=new Emei(champions);
        champions.setWudang(wudang);
        champions.setShaolin(shaolin);
        champions.setEmei(emei);
        wudang.sendAlliance("武当弟子被少林大力金刚指所杀");
        emei.sendAlliance("峨眉弟子被少林大力金刚指所杀");
        shaolin.sendAlliance("少林弟子绝不会做出这种事情");
    }
}

首先创建武林盟主类Champions 并传入到各个门派类,接着调用武林盟主类的setter方法传入各个门派类,最后调用各个门派的sendAlliance方法通过武林盟主类向其他门派发送消息。

输出结果为:

少林收到消息:武当弟子被少林大力金刚指所杀 
少林收到消息:峨眉弟子被少林大力金刚指所杀 
武当收到消息:少林弟子绝不会做出这种事情 
峨眉收到消息:少林弟子绝不会做出这种事情

你可能感兴趣的:(java,设计模式)