设计模式

观察者模式

一、简介

观察者模式定义了对象间的一对多依赖关系,让一个或者多个观察者对象观察一个主题对象。当主题对象的状态发生变化时,系统能通知所有的依赖于此对象的观察者对象,从而使得观察者对象能够自动更新。
    在观察者模式中,被观察的对象也被称为目标或者主题,依赖的对象被称为观察者(Observer)。

二、示例

1、下面一个简单的示例来示范观察者模式,程序先提供一个观察者接口。
1
2
3
public interface Observer {
void update(Observable observable,Object arg);
}
这是一个观察者接口,所有的观察者都应该实现该接口。在该接口的update方法中包含了一个Observable类型的参数,该参数代表被观察对象,也就是前面介绍的目标或主题。

2、一个抽象基类,所有的被观察者都应该实现这个基类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class Observable {
//用一个List对象来保存该对象上所有绑定得事件监听器
List<Observer> observers = new ArrayList<Observer>();
//定义一个方法,用于从该主题上注册观察者
public void registObserver(Observer o){
observers.add(o);
}
//定义一个方法,用于从该主题上删除观察者
public void removeObserver(Observer o){
observers.remove(o);
}

//通知该主题上注册的所有观察者
public void notifyObservers(Object value) {
//遍历注册到该被观察者上的所有观察者
for (Observer o:observers
) {
o.update(this,value);
}
}

}
3、这是一个具体的被观察者,Product,有两个属性,继承了Observable。
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
public class Produce extends Observable {
//定义两个成员变量
private String name;
private double price;

public Produce() {
}

public Produce(String name, double price) {
this.name = name;
this.price = price;
}

public String getName() {
return name;
}

//当程序调用name的setter方法来修改Prodect的name从成员变量时,
//程序自然触发注册到该对象上的所有观察者
public void setName(String name) {
this.name = name;
notifyObservers(name);
}

public double getPrice() {
return price;
}

//当程序调用name的setter方法来修改Prodect的price从成员变量时,
//程序自然触发注册到该对象上的所有观察者
public void setPrice(double price) {
this.price = price;
notifyObservers(price);
}
}
4、观察者对象,用于观察Produce的name成员变量与用于观察Produce的price成员变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class NameObserver implements Observer{

/**
* 实现观察者必须实现的update方法
* @param observable
* @param arg
*/
@Override
public void update(Observable observable, Object arg) {
if (arg instanceof String) {
//将产品的改变值放在name属性中
String name = (String) arg;
//启动一个JFrame来显示被观察者的状态的改变
JFrame jFrame = new JFrame("观察者");
JLabel jLabel = new JLabel("名称改变为:"+name);
jFrame.add(jLabel);
jFrame.pack();
jFrame.setVisible(true);
System.out.println("名称观察者:"+observable+"物品名称已经变为:"+name);
}
}
}
1
2
3
4
5
6
7
8
public class PriceObserver implements Observer {
@Override
public void update(Observable observable, Object arg) {
if (arg instanceof Double) {
System.out.println("价格观察者:"+observable+"物品的价格已经变为:"+arg);
}
}
}
5、主程序,创建一个Product对象(被观察对象),然后向该被观察对上注册两个观察者对象,当主程序调用Product对象的Setter方法来改变对象的状态时,注册在Product对象上的两个观察者对象将被触发。主程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class main {
public static void main(String[] args) {
//创建一个被观察者
Produce produce = new Produce("汽车",100000);
//创建两个观察者
NameObserver nameO = new NameObserver();
PriceObserver priceO = new PriceObserver();
//向被观察者上注册两个观察者对象
produce.registObserver(nameO);
produce.registObserver(priceO);
//程序调用setter方法来改变Product的name和price变量
produce.setName("audi");
produce.setPrice(400000f);
}
}
结果:
名称观察者:com.njupt.observer.Produce@1a6c5a9e物品名称已经变为:audi
价格观察者:com.njupt.observer.Produce@1a6c5a9e物品的价格已经变为:400000.0
文章目录
  1. 1. 一、简介
  2. 2. 二、示例