- 定义
- 类型
- 类图
- 结构
- 有趣的例子
定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
类型:行为类模式
类图:
结构:在最基础的观察者模式中,包括以下四个角色:
- 被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
- 观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
- 具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
- 具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。
有趣的例子
1.假设我们有一情景是这样子的:小孩子在睡觉,醒来后爸爸要给孩子喂东西吃,爷爷要抱小孩子,叔叔要亲小孩子。
从情景中我们分析:首先孩子当前的状态是睡着的,爸爸,爷爷,叔叔都需要观察小孩子睡醒后才能进行一系列动作。那么我们很容易想到的就是在实现的时候将小孩子的类封装到爸爸,爷爷,和叔叔的类中,让爸爸,爷爷,叔叔去主动观察小孩子的状态。这是一种可行的方法,但是此方法需要不断的去监视小孩子的状态,导致爸爸,爷爷,叔叔在小孩子睡着的这段时间一直处于状态,这样是不是太累了。因此我们想到:将这些观察者的类封装到小孩子的类中,让小孩子主动醒来去通知观察者来执行相应的操作,这就是我们所要说的观察者模式。
那么接下来我们来实现这一情景需求:
Test.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
class WakenUpEvent {
private long time;
private String location;
private Child source;
public WakenUpEvent(long time, String location, Child source) {
super();
this.time = time;
this.location = location;
this.source = source;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Child getSource() {
return source;
}
public void setSource(Child source) {
this.source = source;
}
}
class Child implements Runnable {
private java.util.List<WakenUpListener> wakenUplisteners = new ArrayList<WakenUpListener>();
public void addWakenUpListener(WakenUpListener l) {
wakenUplisteners.add(l);
}
public void wakeUp() {
for (int i = 0; i < wakenUplisteners.size(); i++) {
WakenUpListener l = wakenUplisteners.get(i);
l.ActionToWakenUp(new WakenUpEvent(System.currentTimeMillis(),
"bed", this));
}
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.wakeUp();
}
}
class Dad implements WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
System.out.println("feed child");
}
}
class GrandFather implements WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
System.out.println("hug child");
}
}
interface WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent);
}
class PropertyMgr {
private static Properties properties = new Properties();
static {
try {
properties.load(Test.class.getClassLoader().getResourceAsStream(
"zhaowanyue/observer.properties"));
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static String getProperty(String key) {
return properties.getProperty(key);
}
}
public class Test {
public static void main(String[] args) throws IOException {
Child child = new Child();
String[] observers = PropertyMgr.getProperty("observers").split(",");
for (String s : observers) {
try {
child.addWakenUpListener((WakenUpListener) Class.forName(s)
.newInstance());
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}
}
new Thread(child).start();
}
}
observer.properties
observers=zhaowanyue.Dad,zhaowanyue.GrandFather