模式分析:
观察者模式又称为发布/订阅(Publish/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
UML类图:
接口分析:
Observerable:被观察者接口,规定了几个方法,分别是registerObserver():表示将观察者注册到被观察者中,即“订阅”;removeObserver():表示将观察者从被观察者中移除,即“取消订阅”;notifyObservers():当被观察者状态改变的时候,这个方法被调用,通知所有已经注册的观察者。
ConcreteObserverable:被观察者,实现了Observerable接口,对以上的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。注意,该集合的泛型参数应该是Observer,接口类型,而不应该是具体的Observer实现类,这样做的原因是一个被观察者可能会有多个不同实现类的观察者(但都实现了Observer接口),如果限定了某一个具体的类型,那么会导致以后要加入新类型的时候而不得不修改当前类,耦合度过高,这是一个非常不好的行为。(设计原则:面向接口编程而不是面向实现编程)。
Observer:观察者接口,规定了update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。
ConcreteObserver:观察者,实现了update()方法。
DEMO:
//定义被观察者
public interface Observerable {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
//定义观察者
public interface Observer {
public void update(int edition, float cost);
}
public class MagazineData implements Observerable {
private List<Observer> observerList;
private int edition;
private float cost;
public MagazineData(){
observerList = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = observerList.indexOf(observer);
if(i >=0){
observerList.remove(i);
}
}
@Override
public void notifyObservers() {
observerList.stream().forEach(item ->{
item.update(edition, cost);
});
}
public void setInfomation(int edition, float cost){
this.edition = edition;
this.cost = cost;
notifyObservers();
}
}
public class Customer implements Observer{
private String name;
private int edition;
private float cost;
public Customer(String name){
this.name = name;
}
@Override
public void update(int edition, float cost) {
this.edition = edition;
this.cost = cost;
buy();
}
public void buy(){
System.out.println(name+"购买了第"+edition+"期的杂志,花费了"+cost+"元。");
}
}
public static void main(String[] args) {
MagazineData magazineData = new MagazineData();
Observer customerA = new Customer("A");
Observer customerB = new Customer("B");
Observer customerC = new Customer("C");
magazineData.registerObserver(customerA);
magazineData.registerObserver(customerB);
magazineData.registerObserver(customerC);
magazineData.setInfomation(5, 20);
}
推模型:被观察者主动向观察者推送自身的信息,可以是全部信息或者是部分信息。
拉模型:被观察者通过把自身的引用传递给观察者,需要观察者自行通过该引用来获取相关的信息。
认识Java内置的观察者模式:
- java.util.Observerable(类)
- java.util.Observer(接口)
使用场景:
比如我们有两个对象,一个对象依赖于另一个对象的变化而变化,此时我们可以将这两个对象抽象出来,做成接口,利用观察者模式来进行解耦,又或者,当一个对象发生变化的时候,需要通知别的对象来做出改变,但又不知道这样的对象有多少个,此时利用观察者模式非常合适。