资讯专栏INFORMATION COLUMN

设计模式走一遍---观察者模式(下)

aisuhua / 1506人阅读

摘要:上篇我们讲解了观察者模式的一些知识,而且自定义观察者模式的经典代码,传送们设计模式走一遍观察者模式上这篇简单讲一下自带的观察者模式实现代码。注被观察者又被称为主题对象,目标对象。

上篇我们讲解了观察者模式的一些知识,而且自定义观察者模式的经典代码,(传送们:设计模式走一遍---观察者模式(上))

这篇简单讲一下JDK自带的观察者模式实现代码。

对于观察者模式,JDK中提供了一个Observer接口(观察者),一个Observable类(主题对象)。

注:被观察者又被称为主题对象,目标对象。

具体我们来看下源码。

1.观察者接口

public interface Observer {
    /**
     * This method is called whenever the observed *object is changed. 
     *当被观察者发生变化时,该方法将会被调用
     * @param   o     the observable object.
     * @param   arg   an argument passed to the notifyObservers
     *                 method.
     */
    void update(Observable o, Object arg);
}

该接口相当于观察者,里面有一个update(Observable o, Object arg)方法,Observable参数是指主题对象,该参数指明该观察者是属于哪一个主题对象的。

arg参数可以是任意对象,假如主题对象在发送通知时,想要传递什么数据给观察者,那么就可以把数据对象传递给arg参数。

2.主题对象类(方法有点多,我就不放英文解释了)

//主题对象可以是接口、抽象类、具体类,我们上节说
//一般采用抽象类,不过JDK这里使用的是具体类
public class Observable {
    //标记主题对象的状态是否改变
    private boolean changed = false;
    //存放观察者集合,之所以用Vector而不用ArrayList
    //主要是Vector是线程安全的
    private Vector obs;

    public Observable() {
        obs = new Vector<>();
    }

    //添加一个观察者
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    //删除一个观察者
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    
    //标记该对象的状态是否发送了改变
    protected synchronized void setChanged() {
        changed = true;
    }

    //指示该对象不会再发生改变,或者它已经通知了
    //所有观察者
    protected synchronized void clearChanged() {
        changed = false;
    }
    
    
    //测试对象是否发生了改变。当且仅当在此对象最近
    //调用了setChange()方法
    public synchronized boolean hasChanged() {
        return changed;
    }

    //如果hasChanged()方法指示此对象发送了改变,
    //则通知所有观察者,并且调用clearChanged()方法
    //指示此对象不再改变
    public void notifyObservers() {
        notifyObservers(null);
    }

    //与上面没有参数的同名方法相同,只是如果这个方
    //法的arg参数可以接受主题对象想要传递观察者的数据对象
    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);
    }

    //删除所有观察者
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    //返回观察者的数量
    public synchronized int countObservers() {
        return obs.size();
    }
}

该具体类Observable相当于主题对象,实现的主要功能就是当自己的状态发送改变时,通知观察者,观察者再根据通知,在update方法做出相应的反应。

简单写个Demo测试下。

public class Test {
    public static void main(String[] args){
        //创建一个主题对象
        AnimalSubject animalSubject = new AnimalSubject();
        animalSubject.addObserver(new DogObsever());
        animalSubject.addObserver(new LionObsever());
        //状态发生改变
        animalSubject.setChanged();
        //通知观察者
        animalSubject.notifyObservers();
    }
}

//动物主题,弄子类方便拓展主题对象功能
class AnimalSubject extends Observable{
    //不过我就不新增代码、方法了

    //不覆盖下的话,上面的测试调用不了setChange()方法
    //为了方便测试,覆盖重写下
    @Override
    protected synchronized void setChanged() {
        super.setChanged();
    }
}
class DogObsever implements Observer{
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到通知,小狗观察者正在做出相应处理");
    }
}

class LionObsever implements Observer{
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到通知,狮子观察者正在做出相应处理");
    }
}

打印结果

收到通知,狮子观察者正在做出相应处理
收到通知,小狗观察者正在做出相应处理

从上面的代码中我们可以发现JDk内置的观察者模式中的主题对象是一个具体类,而不是一个抽象类或接口,而且setChange()方法还被保护起来了(被定义为protected),这就意味着,要在别的类中调用该方法,那么我们必须继承在子类中重写覆盖该方法。显然,我觉得这很不友好.....

可能这也是JDK内置的观察者模式很少被拿来使用 的原因吧,一般都是自己来自定义观察者模式。

希望大家能够动手写一下这些代码,可能会碰到一些你没想到的问题。

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多需要的人

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77020.html

相关文章

  • 设计模式一遍---察者模式

    摘要:观察者模式的别名包括发布订阅模式模型视图模式源监听器模式或从属者模式。而观察者一般也会做出对象的响应观察者模式属于行为型模式观察者模式主要解决的问题一方的状态发生了变化,依赖于这一方的观察者立即能收到通知。参考书籍设计模式版。 1 红灯车过,人停;绿灯人过,车停。每天走在马路上,到处可见红绿灯指挥着我们什么时候可以过马路,什么时候不能过马路。无论是人还是车,都时刻关注着红绿灯的状态,一...

    justCoding 评论0 收藏0
  • 简单 16步一遍 Laravel Echo 的使用

    摘要:在国内,个人还是不推荐使用,访问速度有所影响,而且其还是一个商业产品。今天利用最简便的步,走一遍代码集成和来使用。代码简单创建监听我们在后端添加一个被创建的事件,并继承。 showImg(https://segmentfault.com/img/remote/1460000015801244?w=904&h=241); 先飚几句英文,说说 Laravel Echo 的作用: One o...

    chavesgu 评论0 收藏0
  • 移动测试中游戏和应用的不同之处

    摘要:今天就说说移动测试中最重要的两个方向。自动化测试完全不同于手游自动化测试手机和手游的开发技术不同,这导致了两者的自动化测试技术是截然不同的。手游和的第二个玩法不同在于探索性。 随着智能设备的普及和移动互联网的兴起,各家互联网巨头纷纷在往移动端布局和转型,同时初创的移动互联网公司也都盯着这个市场希望分一杯羹。在这个大环境下,互联网的重心已经慢慢从Web端转向了移动端,而移动端的软件测试也...

    Jinkey 评论0 收藏0
  • 项目开发的责任感

    摘要:目前我形成了一个项目告一段落就进行一次总结的习惯,总结会对提高自己的思维层次和能力都非常的有帮助,这篇文章主要基于我现在所在的环境,和所在的公司情景来写的关于开发开发过程,我制作了流程化,从文档入手,做数据结构分析数据表结构分析程序结构分析 目前我形成了一个项目告一段落就进行一次总结的习惯,总结会对提高自己的思维层次和能力都非常的有帮助,这篇文章主要基于我现在所在的环境,和所在的公司...

    NickZhou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<