Loading

设计模式之观察者模式

观察者模式在23中模式中应该算比较简单的一种,并没有太大的难度,属于一看就懂的那种。

一、什么是观察者模式

观察者模式又称订阅者模式,观察者模式定义了一种一对多的关系,即多个观察者同时观察被观察者对象。只要被观察者发生变化,所有的观察者就会知道,并自动更新自己。

二、举例说明

最近小米8发布了,那么肯定是会在京东卖,在淘宝卖,以及其他一些网站,那么就可以有以下伪代码

if(发布了新产品) {
    推送产品到淘宝;
    推送产品到京东;
    ......
}

可以看到这样会无限的加下去,代码耦合度高,不利于维护。

如果利用观察者模式,这个问题就能轻易解决了。

三、代码实现

先看看项目的目录,更清晰
1.png

我们首先先定义老东家小米,也就是被观察者

/**
 * 观察者模式 被观察的商品列表
 * 继承Observable接口
 * @author liu
 */
public class ProductList extends Observable {
    // 存放商品
    private List<String> productList = null;
    // 使用单例模式,类的唯一实例
    private static ProductList instance;
    // 私有构造方法
    private ProductList() {}

    /**
     * 返回类的唯一实例
     * @return
     */
    public static ProductList getInstance() {
        if(instance == null) {
            instance = new ProductList();
            instance.productList = new ArrayList<String>();
        }
        return instance;
    }

    /**
     * 添加观察者
     * @param observer 要被添加的观察者
     */
    public void addProductListObserver(Observer observer) {
        this.addObserver(observer);
    }

    /**
     * 新增商品
     * @param product
     */
    public void addProduct(String product) {
        // 把商品添加进商品列表
        productList.add(product);
        System.out.println("新增了商品:" + product);
        // 标记被观察的对象已改变
        this.setChanged();
        // 通知观察者,并传递新产品
        this.notifyObservers(product);
    }
}

被观察者继承了Observable 类,在该类里有一些方法可以供被观察者使用。

我们调用了addObserver方法,该方法可以添加观察者,其实它是使用了一个容器去放观察者,源码如下

    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

在addProduct方法中,我们调用了setChanged方法标志被观察者状态已经改变,源码如下

    /**
     * Marks this <tt>Observable</tt> object as having been changed; the
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
     */
    protected synchronized void setChanged() {
        changed = true;
    }

还调用了一个notifyObservers方法,该方法会通知观察者,我的状态已经改变。该方法源码如下

    public void notifyObservers(Object arg) {
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

可以看到在该方法中,调用了观察者实现的update方法(观察者实现的代码在下面)


接着定义马云,也就是观察者一

public class TaobaoObserver implements Observer {

    @Override
    public void update(Observable productList, Object product) {
        String newProduct = (String)product;
        System.out.println("发送新商品" + newProduct + "到淘宝商城");
    }
}

观察者实现了Observer 接口,并实现了该接口中唯一的方法update,该方法在被观察者的状态改变后,就会调用,所以我们可以在这个方法里进行一些操作。



接下来定义刘强东,也就是观察者二

**
 * 观察者 实现了Observer接口
 * @author liu
 */
public class JDObserver implements Observer {

    @Override
    /**
     * 只要改变了 observable 对象就调用此方法。
     */
    public void update(Observable productList, Object product) {
        // 获取改变的商品
        String newProduct = (String)product;
        System.out.println("发送新商品" + newProduct + "到京东商城");
    }
}



一切准备就绪,我们现在来定义一个实现类

public class Test {
    public static void main(String[] args) {
        ProductList pl = ProductList.getInstance();
        JDObserver observer1 = new JDObserver();
        TaobaoObserver observer2 = new TaobaoObserver();
        // 添加观察者
        pl.addProductListObserver(observer1);
        pl.addProductListObserver(observer2);
        // 增加商品
        pl.addProduct("小米8");
    }
}

运行后输出

新增了商品:小米8
发送新商品小米8到淘宝商城
发送新商品小米8到京东商城

可以看到,雷军发布了小米8,马云和刘强东知道之后,马上会把小米8放到自己的网站售卖,实现了很好的协作方式。

posted @ 2018-06-09 17:12  CodeTiger  阅读(24)  评论(0编辑  收藏  举报