1、概念
观察者模式又成为发布订阅模式,是对象的行为模式。观察者定义了一种一对多的以来关系,让多个观察者对象同时监视着被观察着的状态,当被观察者的状态发生变化时,会通知所有的观察者,并让其更新自己。
2、实例
概念永远没有实例能让人对其有更深的理解。接下来通过一个实例来概述观察者模式。如一个商家有一些产品,他和一些电商合作,每当有新产品时,就会把这些产品推送到电商,现在之和淘宝和京东合作,于是会有这样的伪代码:
if(产品库有新产品){
推送产品到淘宝;
推送产品到京东;
}
如果公司又和国美、苏宁、当当等签订合作协议,那么就需要改变这段伪代码。
if(产品库有新产品){
推送产品到淘宝;
推送产品到京东;
推送产品到国美;
推送产品到苏宁;
推送产品到当当;
}
按照这种方法,如果还有其他电商合作,那么还要继续在if语句中增加逻辑。首先如果多大数百家电商,那么if的逻辑就异常复杂了,如果推送商品给淘宝发生异常,需要捕捉异常,避免影响之后的电商接口,导致其不能往下进行,这样代码耦合就会增多。
而观察者模式更易于扩展,责任也更清晰。首先,把每一个电商接口看成一个观察者,每一个观察者都能观察到产品列表(被监听对象)。当公司发布新产品时,就会发送到这个产品列表上,于是产品列表(被监听对象)就发生了变化,这时就可以触发各个电商接口(观察者)发送新产品到对应的合作电商那里,示例如图所示。
这样的好处在于,程序不再出现if语句,观察者会根据被观察对象的变化而做出对应的行为,无论是淘宝、京东或者其他电商接口只要维护自己的逻辑,而无须耦合在一起,同时责任也是明确的。
3、实例代码
观察者模式要同时存在观察者和被观察者双方,观察者可以是多个。在java中,需要去继承java.util.Observer类,先看被观察者——一个产品列表。
public class ProductList extends Observable {
public List<String> productList = null;//产品列表
public static ProductList instance;//类唯一实例
private ProductList(){} //构建方法私有化
/**
* 取得唯一实例
* @return 产品列表唯一实例
*/
public static ProductList getInstance(){
if(instance == null){
instance = new ProductList();
instance.productList = new ArrayList<String>();
}
return instance;
}
/**
* 增加观察者(电商接口)
* observer 观察者
*/
public void addProductListObserver(Observer observer) {
this.addObserver(observer);
}
public void addProduct(String newProduct){
productList.add(newProduct);
System.out.println("产品列表新增了产品:"+newProduct);
this.setChanged();//设置被观察者对象发生变化
this.notifyObservers(newProduct);//通知观察者并产地新产品
}
public static void main(String[] args) {
ProductList observable = ProductList.getInstance();
TaoBaoObserver taoBaoObserver = new TaoBaoObserver();
JingDongObserver jingDongObserver = new JingDongObserver();
observable.addObserver(jingDongObserver);
observable.addObserver(taoBaoObserver);
observable.addProduct("新增产品1");
}
}
这个类的一些基本内容和主要方法如下:
●构建方法私有化,避免通过new的方式创建对象,而是通过getInstance的方法获得产品列表单例,这里使用的是单例模式
●addProductListObserver可以增加一个电商接口(观察者)
●核心逻辑在addProduct方法上。在产品列表上增加一个新的产品,然后调用setChanged方法。这个方法用于告知观察者当前 被观察者发生了变化,如果没有,则无法出发其行为。最后通过notifyObservers告知观察者,让他们发生相应的动作,并将新产品作为参数传递给观察者。
这里已经有了被观察者对象,还要去编写观察者。仍然以淘宝和京东为例,去实现他们的电商接口。作为观察者需要实现java.util.Observer接口的update方法,代码如下:
public class JingDongObserver implements Observer {
@Override
public void update(Observable o , Object product){
String newProduct = (String) product;
System.out.println("发布新产品【"+newProduct+"】同步到京东商城");
}
}
public class TaoBaoObserver implements Observer {
@Override
public void update(Observable o , Object product){
String newProduct = (String) product;
System.out.println("发布新产品【"+newProduct+"】同步到淘宝商城");
}
}
用如下代码来测试两个观察者和产品列表的被观察者。
public static void main(String[] args) {
ProductList observable = ProductList.getInstance();
TaoBaoObserver taoBaoObserver = new TaoBaoObserver();
JingDongObserver jingDongObserver = new JingDongObserver();
**observable.addObserver(jingDongObserver);
observable.addObserver(taoBaoObserver);**
observable.addProduct("新增产品1");
}
加粗的代码是对被观察者注册观察者,这样才能让观察者监控到被观察者的变化情况,运行结果如下:
产品列表新增了产品:新增产品1
发布新产品【新增产品1】同步到淘宝商城
发布新产品【新增产品1】同步到京东商城
以后在产品列表发布新产品,观察者们都可以触发对应的行为了,就不会出现if语句的各类问题了,更利于扩展和维护。