目录
  1. 1. 观察者模式
    1. 1.1. 定义
    2. 1.2. 解释
    3. 1.3. 代码实现
      1. 1.3.1. 准备
      2. 1.3.2. 被观察者
      3. 1.3.3. 观察者
      4. 1.3.4. 场景实现
    4. 1.4. 观察者模式扩展
    5. 1.5. 应用场景
    6. 1.6. 观察者模式优缺点
      1. 1.6.1. 优点
      2. 1.6.2. 缺点
      3. 1.6.3. 注意事项
观察者模式

观察者模式

定义

Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

解释

观察者模式主要有两个角色,一个被观察者,多个观察者,这个被观察者是与多个观察者关联在一起的。
当这个被观察者执行任务后,数据会被更新,所有观察者会被唤醒,自动更新被监控观察者的信息。

代码实现

准备

现在我们输入一个十进制数字,它会被存入被观察者实体中,而这时会将转换为二进制,八进制,十六进制的观察者唤醒。这样输入一个数字,就回打印出这个数字对应的二进制,八进制,十六进制。

被观察者

  1. Subject类
1
2
3
4
5
6
7
8
9
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
package org.example.observer;

import java.util.ArrayList;
import java.util.List;

/**
* 被观察者实体类
*/
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state ;

public int getState(){
return state ;
}

/**
* 这是被观察者需要做的动作
* @param state
*/
public void setState(int state){
System.out.println("输入数字:" + state);
this.state = state ;
notifyAllObservers(); // 这个是当被观察者开始有动作了,那就自动更新所有的观察者
}

/**
* 将观察者加入观察者列表中,这里就包含了所有监控被观察者的观察者。
* @param observer
*/
public void attach(Observer observer){
observers.add(observer);
}

/**
* 唤醒观察者,让观察者自动更新信息
*/
public void notifyAllObservers(){
for (Observer observer : observers){
observer.update();
}
}
}

观察者

  1. 观察者抽象类
1
2
3
4
5
6
7
8
9
package org.example.observer;

/**
* 观察者抽象类
*/
public abstract class Observer {
protected Subject subject ;
public abstract void update();
}
  1. 转换为二进制的观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
package org.example.observer;

public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject ;
// 将当前观察者加入被观察者的观察者列表中
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("输入数字的二进制:"+Integer.toBinaryString(this.subject.getState()));
}
}
  1. 转换为八进制的观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
package org.example.observer;

public class OctalObserver extends Observer {
public OctalObserver(Subject subject){
this.subject = subject ;
// 将当前观察者加入被观察者的观察者列表中
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("输入数字的八进制:"+Integer.toOctalString(this.subject.getState()));
}
}
  1. 转换为十六进制的观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
package org.example.observer;

public class HexObserver extends Observer{
public HexObserver(Subject subject){
this.subject = subject ;
// 将当前观察者加入被观察者的观察者列表中
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("输入数字的十六进制:"+Integer.toHexString(this.subject.getState()));
}
}

场景实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class App {
/**
* 观察者模式
* @param args
*/
public static void main(String[] args) {
// 创建一个被观察者
Subject subject = new Subject();

// 创建三个观察者,这三个被观察者实例会被放入被观察者的观察者列表中
new HexObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);

// 当被观察者开始执行,所有的观察者会被唤醒,自动更新
subject.setState(10);
System.out.println();
subject.setState(20);
}
}

观察者模式扩展

被观察者可以被抽象出来,使得其具有良好的扩展性。

应用场景

  1. 关联行为场景,每个行为之间是关联的。一个行为的触发会影响其他行为。
  2. 事件的多级触发。
  3. 跨系统的消息交换。比如远程调用就需要观察者模式。

观察者模式优缺点

优点

  1. 观察者和被观察者之间是抽象耦合的,这使得观察者和被观察者都很容易的扩展。
  2. 观察者模式建立了一套触发机制,观察者模式每个观察者与被观察者都遵循单一职责,当被观察者被执行,就回触发观察者,这就形成一个触发链。

缺点

  1. 观察者模式需要考虑开发效率和运行效率。java中消息通知是顺序执行,一个观察者失败会影响整体效率,一般采用异步。

注意事项

  1. 广播链问题。观察者模型形成的触发链不能太长,如果太长,触发链中的一个产生错误,整个触发链就毁了。因此在一个观察者模式中最多出现一个对象既是观察者又是被观察者,也就是消息最多转发一次(传递两次)。
  2. 异步处理需要考虑线程安全和队列问题。
文章作者: rack-leen
文章链接: http://yoursite.com/2020/01/04/Java/Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E8%A1%8C%E4%B8%BA%E5%9E%8B%E6%A8%A1%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 rack-leen's blog
打赏
  • 微信
  • 支付宝

评论