GoF设计模式(十九):Observer Pattern 观察者模式

观察者模式,属于行为型设计模式的一种。在该模式下当某个对象发生变化时,会自动通知所有关心该对象的其它对象。避免了其它对象使用轮询这一低效的方式来检查该对象是否发生变化

abstract.jpeg

模式思想

自媒体时代下,写微信公众号的人已经越来越多了。当微信用户关注公众号后,一旦公众号更新文章,关注该公众号的用户即会自动收到其文章消息的推送,而不需要用户时时刻刻主动查看该公众号是否更新了文章。这个例子就很好的体现了我们今天要介绍的设计模式——观察者模式的思想。在该模式下,通常会有多个观察者监听、关注某个主题对象,在主题对象发生变化、更新时,相应的观察者对象会自动收到相应的消息。该模式下通常有四个角色

  • 抽象主题角色:其声明了各具体主题角色的通用方法,包括添加、移除、通知观察者等方法。即本文的WechatOfficialAccount微信公众号类
  • 具体主题角色:其是对抽象主题角色的具体实现,通常其内部会有一个容器用于对观察者实例进行管理。即本文一个名为ProjectDaedalus的微信公众号类
  • 抽象观察者角色:其声明了各具体观察者角色的通用方法,通常其会定义一个update方法,用于在主题角色发生变化、更新时通知自己。即本文的Observer类
  • 具体观察者角色:其是观察者的具体实现类。其实现了update方法,当主题角色发生变化、更新时,即可通过该方法获取更新。即本文的WechatUser微信用户类

实现

现在我们利用Java来实现上文提到的公众号的例子。首先实现抽象主题角色、具体主题角色——即WechatOfficialAccount、ProjectDaedalus类

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* 抽象主题角色: 微信公众号
*/
public interface WechatOfficialAccount {
/**
* 添加观察者
* @param observer
*/
void attach(Observer observer);

/**
* 移除观察者
* @param observer
*/
void detach(Observer observer);

/**
* 向所有观察者发送通知消息
* @param message
*/
void notify(String message);

}
...
/**
* 具体主题角色:微信公众号 ProjectDaedalus
*/
public class ProjectDaedalus implements WechatOfficialAccount{
/**
* 关注该公众号的所有微信用户
*/
private List<Observer> observerList = new LinkedList<>();

/**
* 微信公众号名称
*/
private final String name = "ProjectDaedalus";

/**
* 公众号添加关注者
* @param observer
*/
@Override
public void attach(Observer observer) {
observerList.add(observer);
}

/**
* 公众号移除关注者
* @param observer
*/
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}

/**
* 向所有关注公众号的微信用户推送文章
* @param message
*/
@Override
public void notify(String message) {
for(Observer observer : observerList) {
observer.update(name, message);
}
}
}

然后,来实现所谓的观察者,即Observer、WechatUser类

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
/**
* 抽象观察者
*/
public interface Observer {
/**
* 微信用户接受、更新公众号推送的文章
* @param name 微信公众号名称
* @param message 微信公众号推送的文章
*/
void update(String name, String message);
}
...
/**
* 具体观察者角色:微信用户
*/
public class WechatUser implements Observer {

/**
* 用户名
*/
private String username;

public WechatUser(String username) {
this.username = username;
}

@Override
public void update(String name, String message) {
String str = "<" + username + ">: 收到公众号[" + name + "]推送的文章, 内容如下:";
System.out.println( str );
System.out.println( message );
}
}

现在,让我们看看该模式如何运作

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
/**
* Observer Pattern 观察者模式 Demo
*/
public class ObserverPatternDemo {
public static void main(String[] args) {
// 构造微信公众号的实例
WechatOfficialAccount wechatOfficialAccount = new ProjectDaedalus();

// 构造微信用户的实例
WechatUser user1 = new WechatUser("小明");
WechatUser user2 = new WechatUser("小红");
WechatUser user3 = new WechatUser("小王");

// 上述微信用户均关注本公众号
wechatOfficialAccount.attach(user1);
wechatOfficialAccount.attach(user2);
wechatOfficialAccount.attach(user3);

System.out.println("---------------------- Test 1 ----------------------");
String msg1 = "关于积极推进新形势下阶级斗争的相关通知, ...";
wechatOfficialAccount.notify(msg1);

System.out.println("\n---------------------- Test 2 ----------------------");
// 小王取关了本公众号
wechatOfficialAccount.detach(user3);
String msg2 = "关于恢复以经济建设为中心等若干重大问题的决定, ...";
wechatOfficialAccount.notify(msg2);
}
}

测试结果如下,符合预期

figure 1.jpeg

参考文献

  1. Head First 设计模式 弗里曼著
0%