浅谈Java设计模式系列0x0B---观察者模式

之前我给大家介绍了对象创建型结构型的设计模,式接下来我会为大家介绍行为型的设计模式;
给大家介绍的第一个的行为型设计模式就是观察者模式;

观察者是什么鬼

其实就像在生活中,当你想买一样商品的时候,因为价格太贵,所有你并没有马上入手.但你却会关注它的价格变化,当商品的价格下降的时候,你就会收到通知,并且决定入手;
上面的例子就是一个观察者模式的例子,你就是观察者,商品就是观察目标,当商品的状态发生变化时,观察者会得到通知并做出相应的动作;

模式结构

  • 目标(Subject):被观察的对象,定义了一个观察者的集合,提供增加和删除观察者对象的方法,同时定义了通知方法;
  • 具体目标(ConcreteSubject):目标类的子类,实现目标类中定义的抽象业务逻辑方法;
  • 观察者(Observer):对观察目标的改变做出反应,声明更新数据的接口方法;
  • 具体观察者(ConcreteObserver):维护一个指向具体目标对象的引用,实现观察者接口的更新数据方法,可以调用具体目标类的 attach() 方法将自己添加到目标类的集合中或通过 detach() 方法将自己从目标类的集合中删除;

什么时候可以使用

在以下情况下可以使用观察者模式:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用;
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度;
  • 一个对象必须通知其他对象,而并不知道这些对象是谁;
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制;

代码示例

代码参考
本次以前面购买商品的例子来实现观察者模式;

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* 抽象观察者类
*/

public interface Observer {
void update(String state);
}
/**
* 抽象目标类
*/

public abstract class PhoneSubject {
// 观察者的列表
protected List<Observer> list = new ArrayList<>();

/**
* 注册观察者对象
*/

public void attach(Observer observer)
{

list.add(observer);
System.out.println("Observer attached");
}

/**
* 删除观察者模式
*/

public void detach(Observer observer)
{

list.remove(observer);
System.out.println("Observer detached");
}
public abstract void notifyObservers();
}
/**
* 具体目标类
*/

public class IPhone extends PhoneSubject {
private String state;
/**
* 商品的优惠活动
*/

public void preferential(){
this.state = "the iPhone is on promotion.";
notifyObservers();
}
/**
* 当商品状态改变时,调用通知方法
*/

@Override
public void notifyObservers() {
for(Observer o:list){
o.update(state);//调用观察者的更新方法,进行相应的操作
}
}
}
/**
* 具体观察者类
*/

public class Consumer implements Observer{
private String state;
@Override
public void update(String state) {
//更新状态
this.state=state;
System.out.println(state);
}
}

/**
* 测试类
*/

public class Client {
public static void main(String[] args)
{


IPhone iPhone=new IPhone();
Observer consumer = new Consumer();
iPhone.attach(consumer);
iPhone.preferential();

}
}

运行结果

1
2
Observer attached
the iPhone is on promotion.

总结

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新;
观察者模式可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立一个抽象的耦合,支持广播通信;
但是如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,而且如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;