设计模式——观察者模式

简介——什么是观察者模式

观察者模式是一种定义对象相互之间依赖关系的一种设计模式,它属于设计模式中的行为模式,通过发布/订阅的方式在对象之间互相传送消息

一般观察者使用步骤

  1. 订阅事件(addObserver)
  2. 被观察者发布事件
  3. 观察者响应事件

举例说明

我们可以用一个例子来解释一下观察者模式,犯罪嫌疑人与警察的例子
角色定义

  • 犯罪嫌疑人(被观察者)
  • 警察(观察者)

分析
当警察对犯罪嫌疑人进行盯梢的时候,一旦犯罪嫌疑人选择逃跑或其它不利于抓捕的行为时,警察就会做出一系列反应,所以在本案例中,犯罪嫌疑人就是被观察的对象,而警察就是观察者,也叫盯梢者
我们来看一下案例的一个流程图

当然这里订阅事件,不是犯罪嫌疑人(被观察者)自已订阅的,但这不影响我们举例。
在本案例中,观察者的身份可能有多个,比如说警察或军人,因为对于特殊重大案情,可能需要武警部队参加抓捕,比如说我们边境缉毒案件,但他们的目的都是一致的——抓捕嫌疑人,只不过在本案件中,他们所做的具体的事不一样。

手写代码

1. 定义被观察者接口(注册或添加事件、删除事件、通知事件)

public interface Observable {
    /**
     * 注册/添加观察者
     *
     * @param observer 观察者
     */
    public void addObserver(Observer observer);

    /**
     * 移动观察者
     *
     * @param observer 观察者
     */
    public void removeObserver(Observer observer);

    /**
     * 通知所有的观察者
     */
    public void notifyObservers();
}

2. 定义观察者统一接口,处理事件

public interface Observer {
    /**
     * 根据不同的事件,做出不同的反应
     *
     * @param event event
     */
    public void handle(Event event);
}

3. 定义枚举事件类型

public enum Event {
    //玩
    PLAY(1),
    //逃跑
    RUN(2);
    
    Integer index;
    /**
     * 构造
     *
     * @param index
     */
    Event(Integer index) {
        this.index = index;
    }


    public Integer getIndex() {
        return this.index;
    }
}

4. 定义具体被观察者(X犯罪嫌疑人)

在被观察者里面有一个用于维护订阅了事件的被观察者集合

public class BadMan implements Observable {

    // Observer集合
    private final List<Observer> observers = new LinkedList<>();

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

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

    @Override
    public void notifyObservers(Event event) {
        this.observers.forEach(observer -> observer.handle(event));
    }

    /**
     * 逃跑行为
     */
    public void runAction() {
        System.out.println("犯罪嫌疑人 逃跑");
        notifyObservers(Event.RUN);
    }

    /**
     * 玩行为
     */
    public void playAction() {
        System.out.println("犯罪嫌疑人 玩");
        notifyObservers(Event.PLAY);
    }
}

5. 定义具体的观察者(警察A 和 警察B)

public class PoliceA implements Observer {
    @Override
    public void handle(Event event) {
        System.out.println("PoliceA:receive event = " + event.name());
        if (event == Event.PLAY) {
            System.out.println("PoliceA: 他要玩就让他玩吧");
        } else if (event == Event.RUN) {
            System.out.println("PoliceA: 守住A口");
        }
    }
}


public class PoliceB implements Observer {
    @Override
    public void handle(Event event) {
        System.out.println("PoliceB:receive event = " + event.name());
        if (event == Event.PLAY) {
            System.out.println("PoliceB: 他要玩就让他玩吧");
        } else if (event == Event.RUN) {
            System.out.println("PoliceB: 守住B口");
        }
    }
}

6. 测试

    public static void main(String[] args) {
        BadMan badMan = new BadMan();

        badMan.addObserver(new PoliceA());
        badMan.addObserver(new PoliceB());

        badMan.playAction();
        badMan.runAction();

    }

运行效果

犯罪嫌疑人 玩
PoliceA:receive event = PLAY
PoliceA: 他要玩就让他玩吧
PoliceB:receive event = PLAY
PoliceB: 他要玩就让他玩吧
犯罪嫌疑人 逃跑
PoliceA:receive event = RUN
PoliceA: 守住A口
PoliceB:receive event = RUN
PoliceB: 守住B口

JDK中自带的实现工具

被观察者 java.util.Observable
观察者 java.util.Observer
Observable类源码,里面也是定义了一个Observer集合,有两个重载的notifyObservers方法,与我们代码不同的是,里面有一个changed变量,在notifyObservers方法里面,需要我们手动地将chaned改为true,才能将事件通知给Observer

Observer类源码,里面定义了一个update方法,可以传入事件产生源,和 一个其它参数

1. 定义被具体被观察者,继承Observable

public class BadMan extends Observable {

    /**
     * 逃跑行为
     */
    public void runAction() {
        System.out.println("犯罪嫌疑人 逃跑");
        setChanged();
        notifyObservers(Event.RUN);
    }

    /**
     * 玩行为
     */
    public void playAction() {
        System.out.println("犯罪嫌疑人 玩");
        setChanged();
        notifyObservers(Event.PLAY);
    }
}

2. 定义两个观察者,警察A 警察 B

public class PoliceA implements Observer {
    /**
     * 产生反应
     *
     * @param o   源、即被观察者
     * @param arg event事件
     */
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof Event) {
            Event event = (Event) arg;
            System.out.println("Police A: receive event " + event.name());
            if (event == Event.RUN) {
                System.out.println("Police A: 守住A口");
            } else if (event == Event.PLAY) {
                System.out.println("Police A: 他要玩让他玩吧");
            }
        }
    }
}


public class PoliceB implements Observer {

    /**
     * 产生反应
     *
     * @param o   源、即被观察者
     * @param arg event事件
     */
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof Event) {
            Event event = (Event) arg;
            System.out.println("Police B: receive event " + event.name());
            if (event == Event.RUN) {
                System.out.println("Police B: 守住B口");
            } else if (event == Event.PLAY) {
                System.out.println("Police B: 他要玩让他玩吧");
            }
        }
    }
}

3. 测试

    public static void main(String[] args) {
        BadMan badMan = new BadMan();
        badMan.addObserver(new PoliceA());
        badMan.addObserver(new PoliceB());
        badMan.playAction();
        badMan.runAction();
    }

运行效果

犯罪嫌疑人 玩
Police B: receive event PLAY
Police B: 他要玩让他玩吧
Police A: receive event PLAY
Police A: 他要玩让他玩吧
犯罪嫌疑人 逃跑
Police B: receive event RUN
Police B: 守住B口
Police A: receive event RUN
Police A: 守住A口
posted @ 2021-03-29 13:30  心若向阳花自开  阅读(336)  评论(0编辑  收藏  举报