设计模式之观察者模式

本文详细介绍了如何在Java中实现观察者模式,包括目标对象的定义、观察者接口及其实现、推模型和拉模型的比较。通过具体的代码示例展示了如何创建目标对象、观察者接口以及如何在主程序中订阅和发布消息。此外,还对比了Java API自带的观察者模式调用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.观察者模式创建步骤
    1.目标(被观察者)对象的定义
    2.具体目标对象的定义
    3.观察者接口的定义
    4.观察者的具体实现

2.观察者的两种实现方式:推模型 和 拉模型
    推模型:
    目标对象主动向观察者推送目标得的详细信息
    推送的信息通常是目标对象的全部或者部分数据

    拉模型:
    目标对象再通知观察者时,只传递少量信息
    如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中啦数据;
    一般这种模型的实现,会把目标对象通过update方法传递给观察者

3.比较两种模型
    推模型会使观察者对象难以复用
    拉模型:update方法的参数目标对象本身,基本上可以适用各种情况的需要

4.Java实现与自己实现的对比

    1.不需要在定义观察者和目标的接口了,JDK已经实现了
    2.具体的目标实现里不需要在维护观察者的注册信息了,因为Java中的Observable类里面已经实现了;
    3.触发通知的方式有一点变化,要先调用setChange方法,这是Java为了实现更加精确的触发功能而提供的功能
    4.具体观察者的实现里,update方法其实能同时支持推模型和拉模型。

5.观察者优缺点
    优点:
    1.观察者实现了观察者和目标之间的抽象耦合
    2.观察者模式实现动态的联动
    3.观察者模式支持广播的发送
    缺点:
    1.可能会引起无谓的操作

6.观察者实现代码示例:
    1)观察者模式目标对象的创建
/*   拉模型的实现
*  目标对象,该对象知道观察他的观察者,并提供注册(添加) 和删除观察者的接口
* */
public class Subject {
    // 用来保存被注册的观察者对象
    private List<Observer> mObservers = new ArrayList<>();

    // 添加注册的观察者
    public void attach(Observer observer){
        mObservers.add(observer);

    }
    //删除注册的观察者
    public void detach(Observer observer){
        mObservers.remove(observer);
    }
    //更新观察者的数据
    protected void notifyObserver(){
       for (Observer observer : mObservers){
           observer.update(this);
       }
    }
}
2)观察者接口创建
/*
* 创建观察者接口,定义一个更新的接口实时更新观察者的数据
* */
public interface Observer {
    void update(Subject subject);
}
3)继承目标类(即被观察者)实现实体目标类
/*
*  具体的目标对象 负责把数据信息存入到相应的观察者对象中
* */
public class EntrySubject extends Subject {
    // 目标对象的状态
    private String subjectStates;

    public String getSubjectStates() {
        return subjectStates;
    }

    public void setSubjectStates(String subjectStates) {
        this.subjectStates = subjectStates;
        this.notifyObserver();
    }
}

4)实现观察者接口,创建实体观察者类
public class EntryObserver implements Observer {

    // 观察者状态
    private String observerStatus;
    private static final String TAG = "EntryObserver";

    // 设置观察者做出的反应
    private String feel;

    public String getFeel() {
        return feel;
    }

    public void setFeel(String feel) {
        this.feel = feel;
    }

    @Override
    public void update(Subject subject) {
        observerStatus = ((EntrySubject) subject).getSubjectStates();
        Log.d(TAG, "SubjectStatus is " + observerStatus +", ObserverFeel"+ feel);
    }
}

5)主线程中观察者订阅目标对象(被观察者)
 
        // 1.创建目标(被观察者)
        EntrySubject subject = new EntrySubject();

        // 2. 创建观察者
        EntryObserver observer = new EntryObserver();
        observer.setFeel("haha");
        EntryObserver observer1 = new EntryObserver();
        observer1.setFeel("hei hei");

        // 3.注册观察者
        subject.attach(observer);
        subject.attach(observer1);

        // 4.发布消息
        subject.setSubjectStates("hello world");

7.Java中的API自带的观察者调用代码示例
1)继承Java中的Observable类来创建目标类
public class JavaOfSubject extends Observable{
    private String content;


    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        this.setChanged();//该方法必须调用
        //主动通知,推模式
        this.notifyObservers(content);
        // 拉模式 调用下面方法
        //this.notifyObservers();
    }
}
2)继承Java中的Observer类来实现观察者类
/*
* Java下的Observer观察者
* */
public class JavaOfObserver implements Observer {
    private String ObserverName;
    private static final String TAG = "JavaOfObserver";
    @Override
    public void update(Observable o, Object arg) {
        // 方式一:推模式
        Log.d(TAG,ObserverName + " 收到消息,目标发来的信息是" + arg);
        // 方式二:拉模式
        Log.d(TAG, ObserverName + "收到消息,主动到目标对象中去拉,拉的内容就是" + ((JavaOfSubject) o).getContent());
    }

    public String getObserverName() {
        return ObserverName;
    }


    public void setObserverName(String observerName) {
        ObserverName = observerName;
    }
}
3)主线程中观察者订阅目标对象(被观察者)
        //创建目标对象(被观察者)
        JavaOfSubject subject = new JavaOfSubject();
        // 创建观察者
        JavaOfObserver observer = new JavaOfObserver();
        observer.setObserverName("张三");
        JavaOfObserver observer1 = new JavaOfObserver();
        observer1.setObserverName("李四");
        // 注册观察者
        subject.addObserver(observer);
        subject.addObserver(observer1);
        // 更新目标数据
        subject.setContent("你们好呀!");

8.观察者示例展示
// 该接口是给目标发生改变时被通知的观察者对象调用
public interface Observer {
    // 更新的接口方法
    void update(WeatherSubject subject);
    // 设置观察者名称
    void setObserverName(String observerName);

    // 取得观察者名称
    public String getObserverName();

}


public abstract class WeatherSubject {
    //用来保存注册观察者对象
    public List<Observer> mObservers = new ArrayList<>();
    // 用来添加订阅目标对象的观察者
    public void attach(Observer observer){
        mObservers.add(observer);
    }
    // 删除集合中订阅目标对象的观察者
    public void detach(Observer observer){
        mObservers.remove(observer);
    }
    protected abstract void notifyObservers();

}

public class EntryWeatherObserver implements Observer{

    private static final String TAG = "Weather";
    private String observerName;
    // 天气的情况的内容
    private String weatherContent;

    //提醒的内容
    private String remindThing;

    public String getRemindThing() {
        return remindThing;
    }

    public void setRemindThing(String remindThing) {
        this.remindThing = remindThing;
    }

    @Override
    public void update(WeatherSubject subject) {
        weatherContent = ((EntryWeatherSubject) subject).getWeatherContent();
        Log.d(TAG, observerName + "收到了" + weatherContent+"," + remindThing);
    }

    @Override
    public void setObserverName(String observerName) {
        this.observerName = observerName;
    }

    @Override
    public String getObserverName() {
        return observerName;
    }
}

public class EntryWeatherSubject extends WeatherSubject {
    private String weatherContent;
    @Override
    protected void notifyObservers() {
        // 循环所有的注册的观察者
        for (Observer observer : mObservers) {
            // 规则是:
            // 张三 需要“下雨” 条件通知 其他条件不通知
            // 李四 需要 "下雨" 或者“下雪” 的条件通知其他条件不通知

            if ("下雨".equals(this.getWeatherContent())){
                if ("张三".equals(observer.getObserverName())){
                    observer.update(this);
                }
                if ("李四".equals(observer.getObserverName())){
                    observer.update(this);
                }
            }
            //如果天气是下雪
            if ("下雪".equals(this.getWeatherContent())){
                if ("李四".equals(observer.getObserverName()))
                observer.update(this);
            }


        }
    }

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;
        this.notifyObservers();
    }
}
主线程中观察者订阅目标
        // 1.创建目标
        EntryWeatherSubject subject = new EntryWeatherSubject();
        //2. 创建观察者
        EntryWeatherObserver ZhanSan = new EntryWeatherObserver();
        ZhanSan.setObserverName("张三");
        ZhanSan.setRemindThing("天要下雨了");
        EntryWeatherObserver LiSi = new EntryWeatherObserver();
        LiSi.setObserverName("李四");
        LiSi.setRemindThing("明天雨夹雪");
        // 3.注册观察者
        subject.attach(ZhanSan);
        subject.attach(LiSi);
        // 4.目标发布天气了
        subject.setWeatherContent("下雪");






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值