观察者模式

  当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式

  场景:学生1和2观察等待着老师布置作业,老师通过微信布置完作业,学生1和2便同时接收到了通知,但学生1决定再看会电视,学生2决定马上写作业

  在该场景中,老师为被观察的对象,当该对象发生了变化(布置作业),则自动通知到了依赖他的学生1和2,然后1和2根据通知做出不同的响应

  

  被观察的老师实现类:做法是继承Observable类,触发动作后调用父类的setChanged(对象变化)和notifyObservers(通知依赖他的对象)   ——文末有Observable源码解析

复制代码
import java.util.Observable;

/**
 * 老师布置的作业及时通知到stu1和stu2
 * stu1和stu2通过观察模式实现老师布置作业后的动作
 * @author test11
 */
public class Teacher extends Observable {

    /**
     * 布置作业
     */
    public void giveWork(){
        String work = "默写课文一遍";
        System.out.println("开始布置作业");
        super.setChanged();
        super.notifyObservers(work);
    }

}
复制代码

  观察老师的两个对象学生1和2,实现Observer接口,在update方法中去更新自己的后续操作

复制代码
import java.util.Observable;
import java.util.Observer;

/**
 * 学生通过监听老师布置作业的动作,完成后续动作
 * @author test11
 */
public class Stu1 implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("老师布置作业了," + arg.toString());
        System.out.println("stu1决定再看会电视");
    }
}
复制代码
复制代码
import java.util.Observable;
import java.util.Observer;

/**
 * 学生通过监听老师布置作业的动作,完成后续动作
 * @author test11
 */
public class Stu2 implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("老师布置作业了," + arg.toString());
        System.out.println("stu2决定马上写作业");
    }
}
复制代码

  老师做出动作,并通知他依赖的对象立即做出响应:

复制代码
import java.util.Observable;

/**
 * 老师布置的作业及时通知到stu1和stu2
 * stu1和stu2通过观察模式实现老师布置作业后的动作
 * @author test11
 */
public class Teacher extends Observable {

    /**
     * 布置作业
     */
    public void giveWork(){
        String work = "默写课文一遍";
        System.out.println("开始布置作业");
        super.setChanged();
        super.notifyObservers(work);
    }

}
复制代码

  父类Observable源码解析

复制代码
//被观察的对象变化后调用setChanged修改自己的状态,之后通知所有观察者,见notifyObservers方法
protected synchronized void setChanged() {
        changed = true;
    }

//通知方法首先判断状态是否已改变,状态改变是先决条件,状态改变则获取所有的观察者(见addObserver方法),循环调用观察者的update方法,达到通知的效果
public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
            /* We don't want the Observer doing callbacks into
             * arbitrary code while holding its own Monitor.
             * The code where we extract each Observable from
             * the Vector and store the state of the Observer
             * needs synchronization, but notifying observers
             * does not (should not).  The worst result of any
             * potential race-condition here is that:
             * 1) a newly-added Observer will miss a
             *   notification in progress
             * 2) a recently unregistered Observer will be
             *   wrongly notified when it doesn't care
             */
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

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

//被观察对象实例化时,需要添加观察者,观察者都是实现自Observer接口,在update方法里执行触发操作,添加的观察者放到obs数组对象里,该对象是全局变量,可供被观察对象通知观察者时获取所有对象实例
public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
复制代码

 

posted @   纪煜楷  阅读(486)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示