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语句的各类问题了,更利于扩展和维护。