设计模式08 行为型模式2-迭代器+观察者+中介者

265 阅读17分钟

完整设计模式学习笔记请戳

16 迭代器模式

需求
编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。

传统的方式的问题分析

  1. 将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
  2. 实际上我们的要求是:在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因此这种方案,不能很好实现的遍历的操作
  3. 解决方案:=> 迭代器模式

基本介绍

  1. 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式
  2. 如果我们的集合元素是用不同的方式实现的,有数组,还有 java 的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
  3. 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。
9

对原理类图的说明-即(迭代器模式的角色及职责)

  1. Iterator : 迭代器接口,是系统提供,含义 hasNext, next, remove
  2. ConcreteIterator : 具体的迭代器类,管理迭代
  3. Aggregate :一个统一的聚合接口, 将客户端和具体聚合解耦
  4. ConcreteAggreage : 具体的聚合持有对象集合, 并提供一个方法,返回一个迭代器, 该迭代器可以正确遍历集合
  5. Client :客户端, 通过 Iterator 和 Aggregate 依赖子类

代码实现

  1. 应用实例要求 编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。

  2. 设计思路分析 10

  3. 代码实现

① 迭代器接口Iterator 使用jdk提供的java.util.Iterator
② 具体的迭代器类 (ConcreteIterator 角色)

public class InfoCollegeIterator implements Iterator {

    List<Department> departmentList;//信息工程学院是以List方式存放系
    int index = -1;//遍历的位置

    public InfoCollegeIterator(List<Department> departmentList) {
        this.departmentList = departmentList;
    }

    @Override
    public boolean hasNext() {
        if (index>=departmentList.size()-1){
            return false;
        }
        index += 1;
        return true;
    }

    @Override
    public Object next() {
        Department department = departmentList.get(index);
        return department;
    }

    //删除方法默认空实现
    @Override
    public void remove() {

    }
}
public class ComputerCollegeIterator implements Iterator {

    //需要知道Department是以怎样的方式存放 => 数组
    Department[] departments;
    int position = 0;//遍历的位置

    public ComputerCollegeIterator(Department[] departments) {
        this.departments = departments;
    }

    @Override
    public boolean hasNext() {
        if (position>=departments.length||departments[position]==null){
            return false;
        }
        return true;
    }

    @Override
    public Object next() {
        Department department = departments[position];
        position += 1;
        return department;
    }

    //删除方法默认空实现
    @Override
    public void remove() {

    }
}

③ 统一的聚合接口 (Aggregate 角色)

public interface College {
    public String getName();
    //增加系的方法
    public void addDepartment(String name,String desc);
    //返回一个迭代器 遍历
    public Iterator createIterator();
}

④ 具体的聚合持有对象集合 (ConcreteAggreage 角色)

public class ComputerColleage implements College {

    Department[] departments;
    int numOfDepartment = 0;//保存当前数组的对象个数

    public ComputerColleage() {
        departments = new Department[5];
        addDepartment("Java","java专业");
        addDepartment("PHP","PHP专业");
        addDepartment("大数据","大数据专业");
    }

    @Override
    public String getName() {
        return "计算机学院";
    }

    @Override
    public void addDepartment(String name, String desc) {
        Department department = new Department(name,desc);
        departments[numOfDepartment] = department;
        numOfDepartment += 1;
    }

    @Override
    public Iterator createIterator() {
        return new ComputerCollegeIterator(departments);
    }
}
public class InfoCollegeIterator implements Iterator {

    List<Department> departmentList;//信息工程学院是以List方式存放系
    int index = -1;//遍历的位置

    public InfoCollegeIterator(List<Department> departmentList) {
        this.departmentList = departmentList;
    }

    @Override
    public boolean hasNext() {
        if (index>=departmentList.size()-1){
            return false;
        }
        index += 1;
        return true;
    }

    @Override
    public Object next() {
        Department department = departmentList.get(index);
        return department;
    }

    //删除方法默认空实现
    @Override
    public void remove() {

    }
}

⑤ 输出类(个人认为有点像外观模式中的外观类)

public class OutputImpl {
    //学院集合
    List<College> collegeList;
    public OutputImpl(List<College> collegeList) {
        this.collegeList = collegeList;
    }

    //遍历所有的许愿  然后调用printDepartment 输出各个学院的系
    public void printCollege(){
        //从collegeList去除所有学院
        //java 中的List已经实现了iterator
        Iterator<College> iterator = collegeList.iterator();
        while (iterator.hasNext()){
            College c = (College)iterator.next();
            System.out.println(c.getName());
            printDepartment(c.createIterator());
        }
    }
    
    //输出 学院输出系
    public void printDepartment(Iterator iterator){
        while (iterator.hasNext()){
            Department d = (Department)iterator.next();
            System.out.println(d.getName()+" -- "+d.getDesc());
        }
    }
}

⑥ 客户端调用

public class Client {
    public static void main(String[] args) {
        //创建学院
        ArrayList<College> collegeList = new ArrayList<>();
        ComputerColleage computerColleage = new ComputerColleage();
        InfoColleage infoColleage = new InfoColleage();
        collegeList.add(computerColleage);
        collegeList.add(infoColleage);
        OutputImpl output = new OutputImpl(collegeList);
        output.printCollege();
    }
}

迭代器模式在 JDK-ArrayList 集合应用的源码分析

JDK 的 ArrayList集合中就使用了迭代器模式

public class IteratorDemo {
    public static void main(String[] args) {
        List<String> a = new ArrayList<>();
        a.add("jack");
        a.add("tom");
        Iterator<String> iterator = a.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
11

对类图的角色分析和说明

  • 内部类 Itr 充当具体实现迭代器 Iterator 的类, 作为 ArrayList 内部类
  • List 就是充当了聚合接口,含有一个 iterator() 方法,返回一个迭代器对象
  • ArrayList 是实现聚合接口 List 的子类,实现了 iterator()
  • Iterator 接口系统提供
  • 迭代器模式解决了 不同集合(ArrayList ,LinkedList) 统一遍历问题

迭代器模式的注意事项和细节

优点

  1. 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
  2. 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
  3. 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
  4. 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式

缺点
每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类

17. 观察者模式

天气预报项目需求,具体要求如下

  1. 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。
  2. 需要设计开放型 API,便于其他第三方也能接入气象站获取数据。
  3. 提供温度、气压和湿度的接口
  4. 测量数据更新时,要能实时的通知给第三方

传统方案
12
或者
13

传统方式代码实现

天气情况 CurrentConditions

public class CurrentConditions {
    // 温度,气压,湿度
    private float temperature;
    private float pressure;
    private float humidity;

    //更新 天气情况,是由 WeatherData 来调用,我使用推送模式
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //显示
    public void display() {
        System.out.println("***Today mTemperature: " + temperature + "***");
        System.out.println("***Today mPressure: " + pressure + "***");
        System.out.println("***Today mHumidity: " + humidity + "***");
    }
}

天气核心类 WeatherData

/**
 * 类是核心
 * 1. 包含最新的天气情况信息
 * 2. 含有 CurrentConditions 对象
 * 3.  当数据有更新时,就主动的调用	CurrentConditions 对象 update 方法(含 display),  这样他们(接入方)就看到最新的信息
 *
 * @author Administrator
 */
public class WeatherData {
    private float temperatrue;
    private float pressure;
    private float humidity;
    private CurrentConditions currentConditions;
    //加入新的第三方
    public WeatherData(CurrentConditions currentConditions) {
        this.currentConditions = currentConditions;
    }

    public float getTemperature() {
        return temperatrue;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    public void dataChange() {
    //调用 接入方的 update
        currentConditions.update(getTemperature(), getPressure(), getHumidity());
    }

    //当数据有更新时,就调用 setData
    public void setData(float temperature, float pressure, float humidity) {
        this.temperatrue = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //调用 dataChange, 将最新的信息 推送给 接入方 currentConditions
        dataChange();
    }
}

客户端测试

public class Client {
    public static void main(String[] args) {
        //创建接入方 currentConditions
        CurrentConditions currentConditions = new CurrentConditions();
        //创建 WeatherData 并将 接入方 currentConditions 传递到 WeatherData 中
        WeatherData weatherData = new WeatherData(currentConditions);

        //更新天气情况
        weatherData.setData(30, 150, 40);
        //天气情况变化
        System.out.println("============天气情况变化=============");
        weatherData.setData(40, 160, 20);

    }
}

传统方式问题分析

  1. 其他第三方接入气象站获取数据的问题
  2. 无法在运行时动态的添加第三方 (新浪网站)
  3. 违反 ocp 原则=>观察者模式
    //在 WeatherData 中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到 dataChange, 不利于维护,也不是动态加入

观察者模式介绍

  1. 观察者模式类似订牛奶业务
  2. 奶站/气象局:Subject
  3. 用户/第三方网站:Observer
  • Subject:登记注册、移除和通知
    • registerObserver: 注 册
    • removeObserver: 移除
    • notifyObservers(): 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送, 看具体需求定
  • Observer:接收输入
  • 观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject 通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户时 Observer,是多的一方。

代码实现天气预报需求

14

① Subject角色(主题) ,登记注册、移除和通知
抽象主题

public interface Subject {
    public void registerObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers();
}

具体主题

/**
 * 类是核心
 * 1. 包含最新的天气情况信息
 * 2. 含有 观察者 使用ArrayList管理
 * 3.  当数据有更新时,就主动的调用	ArrayList  这样他们(接入方)就看到最新的信息
 *
 * @author Administrator
 */
public class WeatherData implements Subject{
    private float temperatrue;
    private float pressure;
    private float humidity;
    //观察者集合
    private ArrayList<Observer> observers;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    public float getTemperature() {
        return temperatrue;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    //当数据有更新时,就调用 setData
    public void setData(float temperature, float pressure, float humidity) {
        this.temperatrue = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }

    public void dataChange() {
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        if (observers.contains(observer)){
            observers.remove(observer);
        }
    }

    @Override
    public void notifyObservers() {
        for (Observer observer: observers) {
            observer.update(getTemperature(),getPressure(),getHumidity());
        }
    }


}

② Observer:接收输入
抽象观察者

/**
 * @author DSH
 * @date 2020/7/14
 * @description 观察者接口,由观察者来实现
 */
public interface Observer {
    public void update(float temperature,float pressure,float humidity);
}

具体观察者

public class CurrentConditions implements Observer {
    // 温度,气压,湿度
    private float temperature;
    private float pressure;
    private float humidity;

    //更新 天气情况,是由 WeatherData 来调用,我使用推送模式
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //显示
    public void display() {
        System.out.println("***Today mTemperature: " + temperature + "***");
        System.out.println("***Today mPressure: " + pressure + "***");
        System.out.println("***Today mHumidity: " + humidity + "***");
    }
}

具体观察者,扩展天气服务站点

public class BaiduSite implements Observer {
    // 温度,气压,湿度
    private float temperature;
    private float pressure;
    private float humidity;

    //更新 天气情况,是由 WeatherData 来调用,我使用推送模式
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //显示
    public void display() {
        System.out.println("***百度数据 气温: " + temperature + "***");
        System.out.println("***百度数据 气压: " + pressure + "***");
        System.out.println("***百度数据 湿度: " + humidity + "***");
    }
}

③ 客户端调用

public class Client {
    public static void main(String[] args) {
        //创建一个WeatherData
        Subject subject = new WeatherData();
        //创建观察者
        Observer observer = new CurrentConditions();
        Observer observer2 = new BaiduSite();
        //注册到weatherData
        subject.registerObserver(observer);
        subject.registerObserver(observer2);
        //通知各个注册的观察者
        ((WeatherData)subject).setData(10f,20f,30f);
    }
}

观察者模式的好处

优点

  1. 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
  2. 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码, 遵守了 ocp 原则。
  3. 解除观察者与主题之间的耦合。让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
  4. 易于扩展,对同一主题新增观察者时无需修改原有代码。

缺点

  • 依赖关系并未完全解除,抽象主题仍然依赖抽象观察者。
  • 使用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。
  • 可能会引起多余的数据通知。

观察者模式在 Jdk 应用的源码分析

Jdk 的 Observable 类就使用了观察者模式

public interface Observer {//(抽象观察者
    //只定义了一个update方法
    void update(Observable o, Object arg);
}

public class Observable {//抽象被观察者
    private boolean changed = false;//定义改变状态,默认为false
    private final ArrayList<Observer> observers;//定义一个观察者list

    public Observable() {//构造函数,初始化一个观察者list来保存观察者
        observers = new ArrayList<>();
    }
    //添加观察者,带同步字段的,所以是线程安全的
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!observers.contains(o)) {
            observers.add(o);
        }
    }

    //删除观察者
    public synchronized void deleteObserver(Observer o) {
        observers.remove(o);
    }

    //通知所以观察者,无参数
    public void notifyObservers() {
        notifyObservers(null);
    }

     //通知所有观察者,带参数
    public void notifyObservers(Object arg) {

        Observer[] arrLocal;
        //加synchronized字段,保证多线程下操作没有问题
        synchronized (this) {
            if (!hasChanged())//这里做了是否发生改变的判断,是为了防止出现无意义的更新
                return;

            arrLocal = observers.toArray(new Observer[observers.size()]);//ArrayList转换成一个临时的数组,这样就防止了通知,添加,移除同时发生可能导致的异常
            clearChanged();///清除改变状态,设置为false
        }
        //遍历逐一通知
        for (int i = arrLocal.length-1; i>=0; i--)
            arrLocal[i].update(this, arg);
    }

    //清楚所有观察者
    public synchronized void deleteObservers() {
        observers.clear();
    }

    //设置被观察者为改变状态,设置为true
    protected synchronized void setChanged() {
        changed = true;
    }

    //清除改变状态,设置为false
    protected synchronized void clearChanged() {
        changed = false;
    }

    //返回当前的改变状态
    public synchronized boolean hasChanged() {
        return changed;
    }

    //观察者数量
    public synchronized int countObservers() {
        return observers.size();
    }
}
15

模式角色分析

  • Observable 的作用和地位等价于 我们前面讲过Subject
  • Observable 是类,不是接口,类中已经实现了核心的方法 ,即管理 Observer 的方法 add.. delete .. notify...
  • Observer 的作用和地位等价于我们前面讲过的 Observer, 有 update
  • Observable 和 Observer 的使用方法和前面讲过的一样,只是 Observable 是类,通过继承来实现观察者模式

18. 中介者模式

需求:智能家庭项目

  1. 智能家庭包括各种设备,闹钟、咖啡机、电视机、窗帘 等
  2. 主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为:闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电视机开始播放

传统方式解决
16

传统的方式的问题分析

  1. 当各电器对象有多种状态改变时,相互之间的调用关系会比较复杂
  2. 各个电器对象彼此联系,你中有我,我中有你,不利于松耦合.
  3. 各个电器对象之间所传递的消息(参数),容易混乱
  4. 当系统增加一个新的电器对象时,或者执行流程改变时,代码的可维护性、扩展性都不理想考虑中介者模式

基本介绍

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

原理类图
17

对原理类图的说明-即(中介者模式的角色及职责)

  1. Mediator 就是抽象中介者,定义了同事对象到中介者对象的接口
  2. Colleague 是抽象同事类
  3. ConcreteMediator 具体的中介者对象, 实现抽象方法, 他需要知道所有的具体的同事类,即以一个集合来管理 HashMap,并接受某个同事对象消息,完成相应的任务
  4. ConcreteColleague 具体的同事类,会有很多, 每个同事只知道自己的行为, 而不了解其他同事类的行为(方法), 但 是他们都依赖中介者对象

代码实现

完成前面的智能家庭的项目,使用中介者模式 18

中介者模式一智能家庭的操作流程:

  1. 创建ConcreMediator对象
public abstract class Mediator {
//将给中介者对象,加入到集合中
public abstract void Register(String colleagueName, Colleague colleague);

//接收消息, 具体的同事对象发出
public abstract void GetMessage(int stateChange, String colleagueName);


public abstract void SendMessage();
}

  1. 创建各个同事类对象,比如: Alarm、CoffeeMachine. TV..
  2. 在创建同事类对象的时候,就直接通过构造器,加入到 colleagueMap
public abstract class Colleague {
    private Mediator mediator;
    public String name;

    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public Mediator getMediator() {
        return mediator;
    }
    
    public abstract void SendMessage(int stateChange);
    
}
public class TV extends Colleague {

    public TV(Mediator mediator, String name) {
        super(mediator, name);
        mediator.Register(name, this);
    }

    @Override
    public void SendMessage(int stateChange) {
        this.GetMediator().GetMessage(stateChange, this.name);
    }

    public void StartTv() {
        System.out.println("It's time to StartTv!");
    }

    public void StopTv() {
        System.out.println("StopTv!");
    }
}

//具体的同事类
public class Alarm extends Colleague {

    //构造器
    public Alarm(Mediator mediator, String name) {
        super(mediator, name);
        //在创建 Alarm 同事对象时,将自己放入到 ConcreteMediator 对象中[集合]
        mediator.Register(name, this);
    }
    
    public void SendAlarm(int stateChange) {
        SendMessage(stateChange);
    }
    
    @Override
    public void SendMessage(int stateChange) {
        this.GetMediator().GetMessage(stateChange, this.name);
    }
    
}

public class CoffeeMachine extends Colleague {

    public CoffeeMachine(Mediator mediator, String name) {
        super(mediator, name);


        mediator.Register(name, this);
    }
    
    @Override
    public void SendMessage(int stateChange) {
        this.GetMediator().GetMessage(stateChange, this.name);
    }
    
    public void StartCoffee() {
        System.out.println("It's time to startcoffee!");
    }
    
    public void FinishCoffee() {
        System.out.println("After 5 minutes!");
        System.out.println("Coffee is ok!");
        SendMessage(0);
    }
}

public class Curtains extends Colleague {
    
    public Curtains(Mediator mediator, String name) { super(mediator, name);
          mediator.Register(name, this);
    }
    
    @Override
    public void SendMessage(int stateChange) {
          this.GetMediator().GetMessage(stateChange, this.name);
    }

    public void UpCurtains() {
        System.out.println("I am holding Up Curtains!");
    }
    
}

  1. 同事类对象,可以调用sendMessage ,最终会去调用 ConcreteMediator的 getMessage方法
//具体的中介者类
public class ConcreteMediator extends Mediator {
    //集合,放入所有的同事对象
    private HashMap<String, Colleague> colleagueMap;
    private HashMap<String, String> interMap;
    
    public ConcreteMediator() {
        colleagueMap = new HashMap<String, Colleague>();
        interMap = new HashMap<String, String>();
    }

    @Override
    public void Register(String colleagueName, Colleague colleague) {
        colleagueMap.put(colleagueName, colleague);
        if (colleague instanceof Alarm) {
            interMap.put("Alarm", colleagueName);
        } else if (colleague instanceof CoffeeMachine) {
            interMap.put("CoffeeMachine", colleagueName);
        } else if (colleague instanceof TV) {
            interMap.put("TV", colleagueName);
        } else if (colleague instanceof Curtains) {
            interMap.put("Curtains", colleagueName);
        }
    }

    //具体中介者的核心方法
    //1. 根据得到消息,完成对应任务
    //2. 中介者在这个方法,协调各个具体的同事对象,完成任务
    @Override
    public void GetMessage(int stateChange, String colleagueName) {
        //处理闹钟发出的消息
        if (colleagueMap.get(colleagueName) instanceof Alarm) {
            if (stateChange == 0) {
                ((CoffeeMachine) (colleagueMap.get(interMap
                        .get("CoffeeMachine")))).StartCoffee();
                ((TV) (colleagueMap.get(interMap.get("TV")))).StartTv();
            } else if (stateChange == 1) {
                ((TV) (colleagueMap.get(interMap.get("TV")))).StopTv();
            }


        } else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) {
            ((Curtains) (colleagueMap.get(interMap.get("Curtains"))))
                    .UpCurtains();

        } else if (colleagueMap.get(colleagueName) instanceof TV) {//如果 TV 发现消息


        } else if (colleagueMap.get(colleagueName) instanceof Curtains) {
            //如果是以窗帘发出的消息,这里处理...
        }

    }
    
    @Override
    public void SendMessage() {

    }


}
  1. getMessage会根据接收到的同事对象发出的消息来协调调用其它的同事对象 ,完成任务
  2. 可以看到getMessage是核心方法,完成相应任务
public class Client {
    public static void main(String[] args) {
        //创建一个中介者对象
        Mediator mediator = new ConcreteMediator();

        //创建 Alarm  并且加入到	ConcreteMediator 对象的 HashMap
        Alarm alarm = new Alarm(mediator, "alarm");
        //创建了 CoffeeMachine 对象,并	且加入到	ConcreteMediator 对象的 HashMap
        CoffeeMachine coffeeMachine = new CoffeeMachine(mediator, "coffeeMachine");
        //创建  Curtains , 并	且加入到	ConcreteMediator 对象的 HashMap
        Curtains curtains = new Curtains(mediator, "curtains");
        TV tV = new TV(mediator, "TV");

        //让闹钟发出消息
         alarm.SendAlarm(0);
         coffeeMachine.FinishCoffee();
         alarm.SendAlarm(1);
    }
}

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

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


设计模式学习代码及笔记)

【代码】
github.com/willShuhuan…
【笔记】
设计模式01 七大原则
设计模式02 类关系与UML类图
设计模式03 创建型模式1-单例+工厂
设计模式04 创建型模式2-原型+建造者
设计模式05 结构型模式1-适配器+桥接+装饰者
设计模式06 结构型模式2-组合+外观+享元+代理
设计模式07 行为型模式1-模板方法+命令+访问者
设计模式08 行为型模式2-迭代器+观察者+中介者
设计模式09 行为型模式3-备忘录+解释器+状态
设计模式10 行为型模式4-策略+职责链