观察者模式小结

从新回顾了一下观察者模式,在网上也有很多不错的文章值得学习,本文为个人笔记,mark之用。

《JAVA与模式》之观察者模式

Java设计模式——观察者模式

1、案例分享

场景:一个时钟对象(被观察对象)每隔1s通知学生(观察者对象),其核心类基于util包下的Observable与Observer

被观察者对象

public class TimeClock extends Observable{

    public static final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private String time = formatter.format(new Date());

    public TimeClock(){
        interval();
    }

    private void interval(){
        Thread thread= new Thread(new Runnable(){
            public void run(){
                while(true){
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    time = formatter.format(new Date());
                    System.out.println("time is:"+time);
                    setChanged();
                    notifyObservers();
                }
            }
        });

        thread.setDaemon(true);
        thread.start();
    }

    public String getTime(){
        return time;
    }
}

观察者对象

public class Student implements Observer {

    private String name;

    public Student(String name){
        this.name = name;
    }


    @Override
    public void update(Observable o, Object arg) {
        System.out.println("student["+this.name+"] 的时间为:"+((TimeClock)o).getTime());
    }
}

测试函数

public class Main extends Thread{

    public static void main(String[] args){
        new Main().start();
    }

    public void run(){

        TimeClock timeClock = new TimeClock();
        Student student1= new Student("kevin.yang");
        Student student2 = new Student("tonny");
        timeClock.addObserver(student1);
        timeClock.addObserver(student2);

        while(true){
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2、jdk 源码分析

在上述的例子中我们用到了两个非常重要的类/接口

Observer接口

/**
* Observer接口为观察者接口
*/
public interface Observer {

     /**
     * update()方法,当被观察者对象的状态发生变化时,被观察者对象
     * 的notifyObservers()方法就会调用这一方法
     */
    void update(Observable o, Object arg);
}

Observable类

public class Observable {

    //标示被观察者的状态是否发生变化
    private boolean changed = false;

    //用于存储观察者的列表
    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);
    }

    /**
     * 
     */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * 如果本对象发生变化,还原changed状态,调用观察者的
     * update方法
     */
    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();
    }

    /**
     * 设置状态为true,标示对象发生变化
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     * 还原状态
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * 返回changed状态,检测对象是否发生变化
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * 返回观察者列表的大小
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值