设计模式——观察者模式

本文说明:在学习《Java EE互联网轻量级框架整合开发》此书时,里面提到了几种设计模式,我在学习这几种设计模式时写了笔记,放上来让大家共同学习,如果有错误,望指出。

本文章由两部分组成:

基本概念+关键代码讲解

完整例子

基本概念+关键代码讲解

观察者模式主要用在y随着x变而变的模型中。比如一个商家有了新产品,只跟京东、淘宝合作,那么就需要把这个新产品推送到京东和淘宝,那么就有了这段伪代码:

if(有新产品) {
    推送到京东;
    推送到淘宝;
}

如果又跟其他商家合作了,就得修改这段逻辑:

if(有新产品) {
    推送到京东;
    推送到淘宝;
    推送到唯品会;
    推送到当当网;
}

如果源源不断要跟新电商合作,源源不断增加新产品,就得不断修改这段逻辑,会导致这段逻辑非常复杂。

这里的自变量是“新产品”,因变量是“推送”。

如果我们可以修改成:京东淘宝唯品会当当网这些人来监听我是不是有新产品,我一增加新产品,它们就给我自动推送到他们的平台上。新增加一个合作电商,就把它扔进监听队列,这样的话会非常省事。

把监听这个动作换成观察,这样就有了观察者模式。

观察者模式有3种类:目标类(核心代码实现)、观察类、测试类。

【目标类】:就是被观察的对象,主要有两个核心动作,增加观察者和增加新产品。

【观察类】:观察目标,目标作出改变,自己就作出改变。

【测试类】:测试逻辑是否实现。

下面主要说说【目标类】和【观察类】。

目标类

我们可以假设产品列表为目标类,既然是目标,肯定有一堆产品对象,我们可以用一个List数组表示。产品增加,我们需要有一个维护产品增加时需要做的逻辑的方法:addProduct()。

那么观察类如何实现它的监听呢?产品变化时,会调用addProduct()方法,要使得观察类跟着变,那么必须把逻辑写到addProduct()里面去。但是如果硬写入,就没有意义了。我们可以利用接口,把接口抛出去让别人实现,然后我们这段随着x改变的y代码就能动态跟着变了。

这里我们得采用 java.util 包里面给我们提供的一些接口,在addProduct()写入一些通过接口能动态实现的方法:比如产品改变了,就“设置改变”,并“通知观察者”。理所当然的,我们的目标类还需要维护观察类的数组,所以与此同时也需要有一个方法能够增加观察者,将观察者加入到我们的目标类队列中。

我们要用到java给我们实现好的监听,可以继承 java.util.Observable 这个类,这样我们可以用到它给我们提供的方法:setChanged(),notifyObservers(),并且它自己给我们维护了一个观察类数组(查看源代码可知为:private Vector<Observer> obs;),也提供了一个维护此数组的方法:addObserver()。

加上我们自己维护的产品对象数组productList以及增加产品的方法addProduct(),将Observable提供给我们的方法按照一定逻辑写入,这个类的功能就基本完成了。实现如下:

//我们自己维护的产品列表数组
private List<String> productList = null;

//增加产品观察者
public void addProductListObserver(Observer observer) {
    this.addObserver(observer);    //Observable提供的方法
}

//增加产品及相应的操作
public void addProduct(String product) {
    this.productList.add(product);
    System.out.println("产品列表新增了产品:" + product);
    this.setChanged();    //Observable提供的方法
    this.notifyObservers(product);    //Observable提供的方法
}

但还有一个问题。

如果每次增加新产品的时候都要new一个新的目标类对象,这样就乱套了。我们只需要一个目标类对象,每次调用时只需要拿到那个目标类对象再进行产品增加才对。所以我们这里需要用到单例模式——每次getInstance时,只得到原来new过的对象。如果没有,就现场给它new一个,代码如下:

//SingleExample类中
private static SingleExample instance = null;

private SingleExample() {}    //使构造方法私有化才能禁止外界的new

private static SingleExample getInstance() {
    if(instance == null) {
        instance = new SingleExample();
    }
    return instance;
}

可以注意到这个getInstance()方法是静态的,所以它的对象也是静态的。

不过如果这个类还有别的属性,比如我们这个例子的产品列表数组,如果我们这个类也要单例的话,也必须实例化唯一一个产品列表数组,所以它也得保持着static,或者通过下面不需要static的方式实例化:

private static ProductList instance;
private List<String> productList = null;

private ProductList() {}

public static ProductList getInstance() {
    if(instance == null) {
        instance = new ProductList();
        //注意这里非static对象的productList的实例化
        instance.productList = new ArrayList<String>();
    }
    return instance;
}

这样我们就实现了目标类,完整代码见最后。

观察类

观察者模式主要逻辑都在被观察者上,观察类只需要实现很少的逻辑。它只需要实现 java.util.Observer 接口的update方法,把被观察者发生变化后需要做的逻辑(比如我们开头说的“推送”)写在update方法之中即可。比如我们可以实现如下:

package com.amiao.design_pattern.observer;
import java.util.Observable;
import java.util.Observer;
public class JingDong implements Observer {
    @Override
    public void update(Observable o, Object product) {
        String newProduct = (String) product;
        System.out.println("京东新增了产品——" + newProduct);
    }
}

完整代码

//主要包含4个类:目标类,2个观察类,测试类

//目标类
package com.amiao.design_pattern.observer;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;    //不要用javax的Observable接口,要用java.util的Observable类
import java.util.Observer;
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();
            //注意这里非static对象的productList的实例化
            instance.productList = new ArrayList<String>();
        }
        return instance;
    }

    public void addProductListObserver(Observer observer) {
        this.addObserver(observer);
    }

    public void addProduct(String product) {
        this.productList.add(product);
        System.out.println("产品列表新增了产品:" + product);
        this.setChanged();
        this.notifyObservers(product);
    }
}

//观察类1
package com.amiao.design_pattern.observer;
import java.util.Observable;
import java.util.Observer;
public class JingDong implements Observer {
    @Override
    public void update(Observable o, Object product) {
        String newProduct = (String) product;
        System.out.println("京东新增了产品——" + newProduct);
    }
}

//观察类2
package com.amiao.design_pattern.observer;
import java.util.Observable;
import java.util.Observer;
public class TaoBao implements Observer {
    @Override
    public void update(Observable o, Object product) {
        String newProduct = (String) product;
        System.out.println("淘宝新增了产品——" + newProduct);
    }
}

//测试类
package com.amiao.design_pattern.observer;
public class TestMain {
    public static void main(String[] args) {
        ProductList productList = ProductList.getInstance();
        productList.addObserver(new JingDong());
        productList.addObserver(new TaoBao());
        productList.addProduct("酸梅巧克力");
        productList.addProduct("雪媚冰淇淋");
    }
}

/*
* 运行结果
* 产品列表新增了产品:酸梅巧克力
* 淘宝新增了产品——酸梅巧克力
* 京东新增了产品——酸梅巧克力
* 产品列表新增了产品:雪媚冰淇淋
* 淘宝新增了产品——雪媚冰淇淋
* 京东新增了产品——雪媚冰淇淋
* */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值