0%

设计模式之观察者模式

一、观察者模式简介

观察者模式的定义

本文章学习自刘望舒的博客。
观察者模式也叫发布–订阅模式,属于行为模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。同时观察者模式还是效率很高的模式,常用语GUI系统,订阅—发布系统,这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得他们之间的依赖性更小,甚至做到毫无依赖。以GUI系统来说,应用的UI更有易变性。

观察者模式UML图:

二、各个类代表的意义及功能

1,各个模块解读

  • Subject:抽象主题(抽象被观察者),它把所有观察者对象保存在一个集合里,每个主题可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生变化时,给所有注册过的观察者发通知。
  • Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知是更新自己。
  • ConcreteObserver:具体观察者,是实现抽象观察者定义的更新的接口,以便在得到主题更改通知是更新自身的状态。

    2,观察者模式简单实现

    我们以微信公众号的订阅来举例,假设用户是观察者,微信公众号是被观察者,有多个用户同时关注了程序猿这个公众号,当这个公众号更新了就会通知这些订阅的用户。接下来看看代码如何实现。

    抽象观察者(Observer)

    1
    2
    3
    public interface Observer {
    public void update(String message);
    }

具体观察者(ConcreteObserver)

微信用户是观察者,里面实现了更新的方法“

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class WeixinUser implements Observer{
//微信用户名
private String name;

public WeixinUser(String name) {
super();
this.name = name;
}

@Override
public void update(String message) {
// TODO Auto-generated method stub
System.out.println(name + "-" + message);
}

}

抽象被观察者(Subject)

抽限主题,提供了attach、detach、notify三个抽象方法:

1
2
3
4
5
6
7
8
9
public interface Subject {

//增加订阅者
void attach(Observer observer);
//删除订阅者
void deatch(Observer observer);
//通知订阅者更新消息
void notify(String message);
}

具体被观察者(ConcreteSubject)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SubscriptionSubject implements Subject{

private List<Observer> weixinUserlist = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
// TODO Auto-generated method stub
weixinUserlist.add(observer);
}

@Override
public void deatch(Observer observer) {
// TODO Auto-generated method stub
weixinUserlist.remove(observer);
}

@Override
public void notify(String message) {
// TODO Auto-generated method stub
for (Observer observer : weixinUserlist) {
observer.update(message);
}
}

}

客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Client {
public static void main(String[] args) {
SubscriptionSubject subscriptionSubject = new SubscriptionSubject();
//创建微信用户
WeixinUser user1 = new WeixinUser("小明");
WeixinUser user2 = new WeixinUser("小红");
WeixinUser user3 = new WeixinUser("小兰");

//订阅公众号
subscriptionSubject.attach(user1);
subscriptionSubject.attach(user2);
subscriptionSubject.attach(user3);

subscriptionSubject.notify("程序猿公众号专栏更新了");
}
}

结果

1
2
3
小明-程序猿公众号专栏更新了
小红-程序猿公众号专栏更新了
小兰-程序猿公众号专栏更新了

3,观察者模式的使用场景和优缺点

使用场景

  • 关联行为场景,需要注意的是,关联行为是可拆分的,而不是组合关系
  • 事件多级触发场景
  • 跨系统的消息交换场景,如消息队列、事件总线的处理机制

    优点

  • 解耦,让耦合的双方都依赖于抽象,从而使得各自的变化都不会影响另一边的变化

缺点

  • 在应用观察者模式的时候要考虑一下开发效率和运行效率的问题,程序包括一个被观察者、多个观察者,开发、调试都比较复杂,而且在java中消息一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。