观察者模式深入理解

观察者模式

要多想,理解后闭上眼睛,想象下生活中哪些场景用到,进而回顾平时代码生涯中哪些场景可以用该模式去实现。

1、概念

观察者模式是什么

有时被称作发布/订阅模式、模型-视图模式,它是对象行为型模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
观察者模式深入理解_第1张图片
主题对应观察者主要有两大类和四小类
两大类:主题、观察者
四小类:抽象主题,具体主题,抽象观察者,具体观察者

具体主题注入所有观察者,主题变动通知观察者,注册观察者,取消观察者
具体观察者注入主题,然后调用主题注册方法把自己注册进主题

画UML类关系图,理清关系

工具:PowerDesigner (离线工具),在线工具(https://www.processon.com/)

观察者模式深入理解_第2张图片

1. 主题Subject

首先定义一个观察者数组,并实现增、删及通知操作。它的职责很简单,就是定义谁能观察,谁不能观察,用Vector是线程同步的,比较安全,也可以使用ArrayList,是线程异步的,但不安全。

public class Subject {

    //增加一个观察者
    void addObserver(Observer observer);
    
    //删除一个观察者
    void deleteObserver(Observer observer);
    
    //通知所有观察者
    void notifyObserver();
   
}

2. 抽象观察者Observer

继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种。

 public interface Observer {
     //更新
     public void update();
 }

3. 具体主题

继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种。
public class ConcreteSubject extends Subject {

//观察者数组
private Vector oVector = new Vector<>();

//增加一个观察者
public void addObserver(Observer observer) {
    this.oVector.add(observer);
}

//删除一个观察者
public void deleteObserver(Observer observer) {
    this.oVector.remove(observer);
}

//通知所有观察者
public void notifyObserver() {
    for(Observer observer : this.oVector) {
        observer.update();
    }
}

}


## 4. 具体观察者

```c
public class ConcreteObserver implements Observer {

    @Override
    public void update() {
        System.out.println("收到消息,进行处理");
    }

}

5. Client客户端

首先创建一个被观察者,然后定义一个观察者,将该被观察者添加到该观察者的观察者数组中,进行测试。

public class Client {
    
    public static void main(String[] args) {
        //创建一个主题
        ConcreteSubject subject = new ConcreteSubject();
        //定义一个观察者
        Observer observer = new ConcreteObserver();
        //观察
        subject.addObserver(observer);
        //开始活动
        subject.doSomething();
    }
    
}

闭上眼睛想象一下生活中有哪些类似的场景,能想多少想多少

  1. 手机丢了,委托别人给其他人发消息通知
  2. 通知老师/老板来了
  3. 拍卖,拍卖师观察最高标价,然后通知给其它竞价者竞价
  4. 在一个目录下建立一个文件,会同时通知目录管理器增加目录,并通知磁盘减少空间,文件是被观察者,目录管理器和磁盘管理器是观察者
  5. 猫叫了一声,吓着了老鼠,也惊到了主人,猫是被观察者,老鼠和人是观察者
  6. 疫情期间:一个人从疫区过来,则这个人是被观察的对象,当体温超过37度,保安拒绝出入公共场所、社区进行登记、医院找拉去隔离治疗、健康码由绿码显示为红码

代码实现案例6(一个人从疫区回来)

代码结构
观察者模式深入理解_第3张图片

1、一个从疫区回来的人

/**
 * 从疫区回来的人
 */
public class EpidemicAreaPerson {
	//体温
    private int temperature;
    //姓名
    private String name;

    public int getTemperature() {
        return temperature;
    }

    public void setTemperature(int temperature) {
        this.temperature = temperature;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2、测体温事件抽象

/**
 * 测体温事件抽象
 */
public interface ThermometerEvent {

    //注册观察者
    void registerObserver(Observer observer);

    //移除观察者
    void removeObserver(Observer observer);

    //通知所有观察者
    public void notifyObserver(EpidemicAreaPerson epidemicAreaPerson);
}

3、测体温事件具体实现

public class ThermometerEventImpl implements ThermometerEvent {

    //观察者数组
    private Vector<Observer> oVector = new Vector<>();

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

    @Override
    public void removeObserver(Observer observer) {
        this.oVector.remove(observer);
    }

    @Override
    public void notifyObserver(EpidemicAreaPerson epidemicAreaPerson) {
        if (epidemicAreaPerson.getTemperature() > 37) {
            for (Observer observer : this.oVector) {
                observer.update(epidemicAreaPerson);
            }
        } else {
            System.out.println("没毛病,因为他是老铁");
        }
    }

}

4、观察者抽象

/**
 * 观察者
 */
public interface Observer {
    //更新
    public void update(EpidemicAreaPerson epidemicAreaPerson);
}

5、具体观察者-医生

public class DoctorObserver implements Observer {
    @Override
    public void update(EpidemicAreaPerson epidemicAreaPerson) {
        System.out.println("医生把" + epidemicAreaPerson.getName() + "带走隔离治疗" + "疑似者温度" + epidemicAreaPerson.getTemperature());
    }
}

6、具体观察者-保安

public class BaoAnObserver implements Observer {
    @Override
    public void update(EpidemicAreaPerson epidemicAreaPerson) {
        System.out.println("疑似者温度" + epidemicAreaPerson.getTemperature() + "保安拒绝" + epidemicAreaPerson.getName() + "出入公共场所");
    }
}

7、模拟事件过程

        //一个超过37度的人
        EpidemicAreaPerson epidemicAreaPerson = new EpidemicAreaPerson();
        epidemicAreaPerson.setName("xiaohong");
        epidemicAreaPerson.setTemperature(38);
        //创建一个主题
        ThermometerEvent subject = new ThermometerEventImpl();
        //定义一个观察者
        Observer observer = new DoctorObserver();
        Observer baoAnObserver = new BaoAnObserver();
        //观察
        subject.registerObserver(observer);
        subject.registerObserver(baoAnObserver);
        //开始活动
        subject.notifyObserver(epidemicAreaPerson);

后面还可以加这样的场景,医生观察者再作为主题,如果该疑似测核酸显示阳性,则上报国家统计,通报媒体,通知疑似者家人。

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