观察者模式:具体代码请参考java.util.Observer和java.util.Observable
观察者模式很简单,目标很明确:当被观察者(Observable111)中的数据变更时,即使通知其下所有的观察者(Observer11)进行变更(update)。
因此,被观察者需要提供 添加观察者,删除观察者,通知观察者等方法,如上类图。
结构很简单,具体不介绍,java.util包中提供了观察者和被观察者的基础类和接口。下面主要说明下这些类中模糊的地方
public class SubjectObservable extends Observable {
private String name;
private String type;
private String colour;
private double price;
/**
* 通过该方法设置变更内容
* setChange()方法用来标记是否进行变更,一般情况只需要调用,但如果遇到有条件的变更时,比如当值大于某个值时才变更,可以先判断条件,然后再setChange
* notifyObservers() 当变更发生时,通过setInfo将所有的变更初始化好,并通知观察者进行变更,但观察者需要变更什么内容,则由观察者自己定义
* notifyObservers(Object args) 该方法notifyObservers(),区别在于由可观察者SubjectObservable推送变更内容,观察者被动接受,类似于广播
* @param name 要变更的数据
* @param type 要变更的数据
* @param colour 要变更的数据
* @param price 要变更的数据
*/
public void setInfo(String name,String type,String colour,double price){
this.name = name;
this.type = type;
this.colour = colour;
this.price = price;
setChanged();
notifyObservers();
// notifyObservers(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public double getPrice() {
return price;
}
/**
* 当price变更时,会通知观察者进行变更(观察者属于被动接受消息)注释部分是这样的
* @param price
*/
public void setPrice(double price) {
this.price = price;
// this.setChanged();
// this.notifyObservers(price);
}
}
如上述注释部分,setInfo来设置需要通知观察者变更的内容,这些内容你可以自己定义,比如爬虫网站数据,发送请求回传的数据等
其中setChange方法是通知观察者的一个标记,因为如果是实时数据,那么通知会很频繁,而观察者可能不需要如此频繁,则可以扩展setChange方法,设置一个判断条件,比如5分钟变更一次等
notifyObservers方法,java.util提供了2个方法:setObservers()和setObservers(Object arg)方法,这2个方法的区别如注释,一个是强制推送给观察者,一个是观察者自己定义要获取的数据
下面是一个观察者的实现
public class Observer2 implements Observer {
private Observable observable;
private String name;
private double price;
/**
* 构造方法
* 定义其使用的可观察者
* 并将当前观察者添加到可观察者中
* @param observable
*/
public Observer2(Observable observable){
this.observable = observable;
observable.addObserver(this);
}
/**
* 实现update方法
* @param o 可观察者对象
* @param arg 变更的参数 由Observers中notifyObservers(Observer o,Object arg)传递过来的变更的对象
*/
@Override
public void update(Observable o, Object arg) {
if(o instanceof SubjectObservable){
SubjectObservable subjectObservable = (SubjectObservable)o;
/**
* 观察者自己定义需要获取的数据
*/
this.name = subjectObservable.getName();
this.price = subjectObservable.getPrice();
System.out.println("name has changed to "+name+",price has changed to "+price);
}
}
}
BUG:虽然java.util中提供了观察者的方式,但是该方式存在很多BUG
1.Observers竟然是一个类,java是单继承,这样就会出现很多不方便的地方。
2.setChange方法是protected,意味这你要使用它必须继承他,不能将Observable的实例组合到你自己的对象中。如:在你定义的class中定义属性 private SubjectObservable oo; oo.setChange();这样违背了策略模式中的多用组合,少用继承的原则。
3.setChange中的changed是私有的,意味着,如果我们是有条件性质的推送通知,那么只能在之前添加判断方法,而不能通过重写setChange方法来实现。虽然这玩意其实没啥影响。