Java描述设计模式:观察者模式

一、观察者模式1、概念描述

观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主题对象在状态发生变化时,会通知所有观察者对象。Redis和常用消息中间件的发布订阅模式,都是基于该原理实现。

2、核心角色

  • 抽象主题角色
抽象主题角色把所有对观察者对象的统一聚集管理,每个主题都可以有一个或多个观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
  • 具体主题角色
将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色。
  • 抽象观察者角色
为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
  • 具体观察者角色
具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态协调同步。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

3、源代码实现

  • 基于消息推送模式
主题对象向观察者推送主题的消息,不管观察者是否需要。
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
 * 观察者设计模式
 */
public class C01_Observer {
    public static void main(String[] args) {
        // 创建主题对象
        ConcreteSubject subject = new ConcreteSubject();
        // 创建观察者对象
        Observer observer1 = new ConcreteObserver("观察者A");
        Observer observer2 = new ConcreteObserver("观察者B");
        // 注册观察者
        subject.attach(observer1);
        subject.attach(observer2);
        // 修改主题状态
        subject.change("New State !");
        /**
         * 主题状态:New State !
         *【观察者A】状态:New State !
         *【观察者B】状态:New State !
         */
    }
}
// 抽象主题角色
abstract class Subject {
    // 保存注册的观察者对象
    private List<Observer> list = new ArrayList<>();
    /**
     * 注册观察者对象
     */
    public void attach (Observer observer){
        list.add(observer);
        System.out.println("注册一个观察者:"+observer.getClass().getName());
    }
    /**
     * 删除观察者对象
     */
    public void delete (Observer observer){
        list.remove(observer);
        System.out.println("删除一个观察者:"+observer);
    }
    /**
     * 通知所有注册的观察者对象
     */
    public void notifyObserver (String newState){
        for (Observer observer : list) {
            observer.update(newState);
        }
    }
}
// 具体主题角色
class ConcreteSubject extends Subject{
    private String state ;
    public String getState (){
        return state ;
    }
    public void change (String newState){
        state = newState;
        System.out.println("主题状态:"+state);
        //状态发生改变,通知各个观察者
        this.notifyObserver(state);
    }
}
// 抽象观察者角色
interface Observer {
    /**
     * 更新接口
     */
    void update (String state);
}
// 具体观察者角色
class ConcreteObserver implements Observer{
    private String name ;
    // 观察者状态
    private String observerState ;
    public ConcreteObserver (String name){
        this.name = name ;
    }
    /**
     * 更新观察者的状态,使其与目标的状态保持一致
     */
    @Override
    public void update(String state) {
        observerState = state ;
        System.out.println("【"+this.name+"】状态:"+observerState);
    }
}
  • 基于消息拉取模式
主题对象在通知观察者的时候,传递少量信息。如果观察者需要该消息内容,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。
该案例基于上述案例修改,观察者获取主题对象的消息话题

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public class C02_Observer_Pull {
    public static void main(String[] args) {
        // 创建主题对象
        ConcreteSubject1 subject = new ConcreteSubject1();
        // 创建观察者对象
        Observer1 observer1 = new ConcreteObserver1("观察者A","JAVA");
        Observer1 observer2 = new ConcreteObserver1("观察者B","MySQL");
        // 注册观察者
        subject.attach(observer1);
        subject.attach(observer2);
        /*
         * 修改主题状态
         * 主题状态:JAVA State !
         * 【观察者A】状态:JAVA State !
         * 主题状态:MySQL State !
         * 【观察者B】状态:MySQL State !
         */
        subject.change("JAVA State !","JAVA");
        subject.change("MySQL State !","MySQL");
    }
}
abstract class Subject1 {
    // 保存注册的观察者对象
    private List<Observer1> list = new ArrayList<>();
    /**
     * 注册观察者对象
     */
    public void attach (Observer1 observer){
        list.add(observer);
    }
    /**
     * 删除观察者对象
     */
    public void delete (Observer1 observer){
        list.remove(observer);
        System.out.println("删除一个观察者:"+observer);
    }
    /**
     * 通知所有注册的观察者对象,传入消息的话题
     */
    public void notifyObservers (String msgTopic){
        for (Observer1 observer : list){
            observer.update(this);
        }
    }
}
class ConcreteSubject1 extends Subject1 {
    private String state ;
    private String msgTopic ;
    public String getState (){
        return state ;
    }
    public String getMsgTopic (){
        return msgTopic ;
    }
    public void change (String newState,String newMsgTopic){
        this.state = newState ;
        this.msgTopic = newMsgTopic ;
        System.out.println("主题状态:"+state);
        this.notifyObservers(msgTopic);
    }
}
 
interface Observer1 {
    /**
     * 更新接口
     * @param subject 传入主题对象,方面获取相应的主题对象的状态
     */
    void update(Subject1 subject);
}
class ConcreteObserver1 implements Observer1{
    private String name ;
    // 选择话题
    private String msgTopic ;
    // 观察者状态
    private String observerState ;
    public ConcreteObserver1 (String name,String msgTopic){
        this.name = name ;
        this.msgTopic = msgTopic ;
    }
    @Override
    public void update(Subject1 subject) {
        ConcreteSubject1 concreteSubject1 = (ConcreteSubject1)subject ;
        // 只有指定话题才拉取消息
        if (concreteSubject1.getMsgTopic().equals(msgTopic)){
            observerState = concreteSubject1.getState();
            System.out.println("【"+this.name+"】状态:"+observerState);
        }
    }
}

更多免费技术资料可关注:annalin1203
posted @ 2020-05-05 09:21  幽暗森林之猪大屁  阅读(175)  评论(0)    收藏  举报