当对象之间存在一对多的关系时,一个对象改变,会主动过通知依赖它的对象,依赖它的对象得到通知并作出相应的修改,观察者模式属于行为型模式。这种模式有时候又被称为发布-订阅模式,模型-视图模式。Spring的事件驱动模型是观察者模式很经典的一个应用。
观察者模式常有几个角色,主题Subject角色,它用来保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的方法;观察者Observer角色,有更新自己的方法,收到主题角色的通知后会调用这个方法;事件,一般用来更新主题的数据。
模拟一个场景:一个商店,分别销售苹果和华为的手机,是为subject角色,观察者就是想要买苹果或者华为手机的用户,当手机到货后,subjecct角色改变,分情况通知用户手机到货了。
首先定义一个观察者接口Observe,其中有一个方法buy(),表示手机到货了,可以购买了。
public interface Observer {
void buy(Subject subject);
}
之后定义一个主题,其中有一个包含许多观察者的list,增加观察者的方法,删除观察者的方法以及通知观察者的方法。这里使用CopyOnWriteArrayList保证线程安全。
public interface Subject {
List<Observer> list = new CopyOnWriteArrayList<>();
void addObserve(Observer observer);
void removeObserve(Observer observer);
void notifyObserve(Observer observer);
}
定义一个具体的主题,在这个例子里是一个商店,当华为或者苹果手机到货后,通知所有的观察者。
public class Shop implements Subject{
private int apple;
private int huawei;
Shop(int apple, int huawei) {
this.apple = apple;
this.huawei = huawei;
}
public int getApple() {
return apple;
}
public int getHuawei() {
return huawei;
}
@Override
public void addObserve(Observer observer) {
list.add(observer);
}
@Override
public void removeObserve(Observer observer) {
if (list.size() > 0) {
list.remove(list.size() - 1);
}
}
@Override
public void notifyObserve() {
for (Observer observer : list) {
observer.buy(this);
}
}
}
定义两个观察者,一个是想买苹果的用户,一个是想买华为的用户,收到通知后,可以主动拉取商店的信息。
public class AppleObserver implements Observer{
@Override
public void buy(Subject subject) {
Shop shop = (Shop) subject;
if (shop.getApple() > 0) {
System.out.println("苹果用户:又有苹果手机到货啦");
} else {
System.out.println("苹果用户:还是没有苹果手机啊");
}
}
}
public class HuaweiObserver implements Observer{
@Override
public void buy(Subject subject) {
Shop shop = (Shop) subject;
if (shop.getHuawei() > 0) {
System.out.println("华为用户:可以买华为手机啦!");
} else {
System.out.println("华为用户:还是没有华为手机啊");
}
}
}
测试:
public static void main(String[] args) {
Shop shop = new Shop(0, 1);
AppleObserver appleObserver = new AppleObserver();
HuaweiObserver huaweiObserver = new HuaweiObserver();
shop.addObserve(appleObserver);
shop.addObserve(huaweiObserver);
shop.notifyObserve();
}
可以看到,两个观察者都收到了被观察者的通知,并做出相应的行为。