3.观察者模式
3.1概述
观察者模式又称发布订阅模式,是对象的行为模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监视着被观察者的状态,当被观察者的状态发生变化,会通知所有观察者,并让其自动更新自己。
现实中有没有这样的例子呢?如智能监控,系统会根据采集到的画面信息做出不同的措施;气象局要监测气温和空气质量,随其变化来发布不同的信息。
下面通过一个电商实例来模拟观察者模式。在现实中,有些条件发生了变化,其他的行为也要发生变化,我们可以用if语句来处理。现在,有一个商家生产一些产品,它和一些电商平台合作,每当有新产品时,就会把这些产品推送到电商,现在商家只和京东、淘宝合作,于是有这样的伪代码:
if (产品库有新产品){
推送新产品到京东;
推送新产品到淘宝;
}
如果商家又和其他平台合作了,就要做如下修改:
if (产品库有新产品){
推送新产品到京东;
推送新产品到淘宝;
推送新产品到当当;
推送新产品到拼多多;
}
如果按这种方法,这时合作平台又发生变化,还要继续在if语句中修改逻辑。平台很少还可以,如果合作平台多达数百家,那这个if的逻辑就十分复杂了,这时如果一家平台出现异常,那也是无法再往下进行了。代码耦合度高,不利于维护,难拓展,不同的电商应该由不同的团队来负责,这些团队又共同负责同一段代码,造成责任不清。
这时采用观察者模式就有优势了,观察者模式更易拓展,责任也更加清晰。首先,把每个电商平台接口视为一个观察者,每个观察者都能观察到产品列表(被监听对象)。当商家发布新商品时,就会发送到这个产品列表上,于是产品列表(被监听对象)就发生了变化,这时就可以触发各个电商接口(观察者)发送新产品到合作的电商。这个过程的示例图如下:
这样,一个对象(电商接口)会去监听另外一个对象(产品列表),当被监听对象(产品列表)发生变化时,对象(电商接口)就会触发一定的行为,以合适变化的逻辑模式,称为观察者模式,电商接口被称为观察者或监听者,而产品对象被称为被观察者或者被监听者。
这样的好处很明显,程序中不再出现if语句,观察者会根据被观察对象的变化而做出对应的行为,每个电商的接口只需要维护自己的逻辑,不用耦合在一起,同时责任也是明确的,产品团队只需要维护产品列表,电商团队可以通过增加观察者去监听产品的电商接口,不会带来if语句导致的责任不清的情况。
3.2实例
观察者模式需要同时存在观察者和被观察者双方,观察者可以是多个。被观察者需要继承java.util.Observable类,观察者实现java.util.Observer接口的update方法。
一个产品列表类(被观察者)代码如下:
public class ProductList extends Observable {
private List<String> productList=null;//产品列表
private static ProductList instance;//唯一实例
private ProductList(){}//私有化构造器
/*
取唯一实例--单例模式
*/
public static ProductList getInstance(){
if(instance==null){
instance=new ProductList();
instance.productList=new ArrayList<String>();
}
return instance;
}
/*
观察者--电商接口
*/
public void addProductListObserver(Observer ob){
this.addObserver(ob);
}
/*
新增产品--核心逻辑
*/
public void addProduct(String newProduct){
productList.add(newProduct);
System.out.println("产品列表增加了新产品--"+newProduct);
this.setChanged();//设置被观察对象发生了变化
this.notifyObservers(newProduct);//通知观察者,并传递新产品参数
}
}
电商接口类(观察者)代码如下:
/************************京东电商接口**************************************/
public class JDObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct =(String) product;
System.out.println("上架新产品【"+newProduct+"】到京东jd.com");
}
}
/*************************淘宝电商接口*************************************/
public class TaoBaoObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct =(String) product;
System.out.println("上架新产品【"+newProduct+"】到淘宝taobao.com");
}
}
测试代码如下:
@Test
public void test(){
ProductList observable =ProductList.getInstance();
TaoBaoObserver taoBao=new TaoBaoObserver();
JDObserver jd=new JDObserver();
//注册观察者
observable.addObserver(jd);
observable.addObserver(taoBao);
//添加新商品
observable.addProduct("2020全新商品S1");
}
运行结果如下。这时,以后如要发布新商品,观察者就能自动触发上架的行为了,不会出现if语句的问题,拓展和维护更加方便。
附:GOF23种设计模式的分类。