定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象,这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动更新。
观察者的实现:
Subject (被观察的对象接口)
---- 规定ConcreateSubject的统一接口。
---每个Subject可以有多个Observer
ConcreateSubject (具体被观察的对象)
维护对所有具体观察者引用的列表。
状态发上改变时会发送通知给所有的注册的观察者。
Observer(观察者接口)
规定ConcreateObserver的同一接口,
定义一个叫做update ()方法,在被观察对象的状态发生改变时会被调用。
ConcreateObserver (具体的观察者):
维护一个ConcreateSubject 的引用。
特定状态与ConcreateSubject同步。
实现Observer接口,通过update()方法接收ConcreateSubject的通知。
实现如下:
(一)被观察对象接口:
public interface Subject {
public void registerObserver (Observer o);// 注册
public void removeObjserver (Observer o);// 取消观察者
public void notifyObserver ();//通知所有观察者更新信息。
}
(二)观察者接口:
public interface Observer {
// 观察者更新信息的方法
public void update (float price);
}
(三)具体的观察者:
public class Doll implements Subject {
private float price;
public Doll(float price) {
this.price = price;
}
public void setPrice(float price) {
// 修改价格时通知所有的观察者
this.price = price;
notifyObserver();
}
// 被观察者维护的一个观察者对象列表
private Vector<Observer> v = new Vector<Observer>();
@Override
public void registerObserver(Observer o) {
v.add(o);
}
@Override
public void removeObjserver(Observer o) {
v.remove(o);
}
@Override
public void notifyObserver() {
// 通知所有的观察者对象
for (Observer o : v) {
o.update(price);// 通知观察者
}
}
}
(四)具体的观察者
public class Person implements Observer {
private String name;
public Person (String name){
this.name = name;
}
@Override
public void update(float price) {
System.out.println(name+"关注的娃娃价格已更新为"+ price);
}
}
(五)测试类:
package com.xiyou.guanchazhe;
public class Test {
public static void main(String[] args) {
// 创建一个被观察者对象
Doll doll = new Doll(3000);
Person p = new Person("小白");
Person p2 = new Person("小黑");
doll.registerObserver(p);// 注册成为一个观察者
doll.registerObserver(p2);
System.out.println("第一轮促销");
doll.setPrice(2698);//价格浮动
System.out.println("第二轮促销");
doll.setPrice(2299);
doll.removeObjserver(p2);//小黑已经移除
System.out.println("第三轮促销");
doll.setPrice(1098);
}
}
运行结如下:
第一轮促销
小白关注的娃娃价格已更新为2698.0
小黑关注的娃娃价格已更新为2698.0
第二轮促销
小白关注的娃娃价格已更新为2299.0
小黑关注的娃娃价格已更新为2299.0
第三轮促销
小白关注的娃娃价格已更新为1098.0
-----------------------------------------------------------------
java中也提供了相应的API
使用如下:
通过继承Observable类实现具体的被观察者对象
public class Doll extends Observable {
private float price;
public Doll(float price) {
this.price = price;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
this.setChanged();// 通知数据已经改变
this.notifyObservers();
}
}
(二)通过实现 java.util.Observer接口来实现具体的观察者:
public class Person implements Observer{
private String name ;
public Person(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof Doll){
Doll doll = (Doll) o;
System.out.println(name+"关注的娃娃价格"+doll.getPrice());
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
Doll doll = new Doll (3000);
Person p1 = new Person ("小白");
Person p2 = new Person("小黑");
doll.addObserver(p2);
doll.addObserver(p1);
System.out.println("第一次促销");
doll.setPrice(2998);
System.out.println("第二次家降价");
doll.setPrice(2698);
doll.deleteObserver(p1);
System.out.println("第三次降价");
doll.setPrice(1998);
}
}
测试结果:
第一次促销
小白关注的娃娃价格2998.0
小黑关注的娃娃价格2998.0
第二次家降价
小白关注的娃娃价格2698.0
小黑关注的娃娃价格2698.0
第三次降价
小黑关注的娃娃价格1998.0
优点:
解除了主题和具体观察者的耦合,让耦合双方都依赖于抽象而不是具体,从而使得各自的变化都不会影响另一边的变化。
缺点:
依赖并未完全解除,抽象通知依旧依赖抽象的观察者。
总结:GUI编程中事件注册就是典型的观察者模式的使用。