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

2023-05-16

观察者模式定义:定义了对象之间的一对多的依赖,这样一来,当一个对象发生改变状态的时候,它的所有依赖者都会收到通知并自动更新。参考如下图:
观察者模式表达图

观察者设计模式也叫发布-订阅模式。
也可以称作:出版者+订阅者 = 观察者模式
在Android中观察者模式的实例有:广播机制,ContentObserver的注册方式,一个是同步的观察者模式,一个是异步的观察者模式。

当两个对象之间松耦合,它们依然可以交互,但是不清楚彼此的细节,观察者提供了一种对象的设计,可以降低之间的耦合,避免对象的双向依赖。
举例:在Android中很多的Listener是观察者模式,比如点击事件的OnClickListener,就是为了避免对象的双向依赖。

—-先来看看Java源码中的观察者模式:

Observer观察者接口:

package com.daming.java.observer;

public interface Observer {

    void update(Observable observable, Object arg);
}

对象Observable 类的实现

package com.daming.java.observer;

import java.util.Vector;

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);
    }

    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();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     * 
     * @return the number of observers of this object.
     */
    public synchronized int countObservers() {
        return obs.size();
    }

}

MyObserver 观察者对象的实现

package com.daming.java.observer;

public class MyObserver implements Observer{

    @Override
    public void update(Observable observable, Object arg) {
        System.out.println("observable :" + observable + "arg :" + arg);
    }
}

MyObserver2 观察者对象的实现

package com.daming.java.observer;

public class MyObserver2 implements Observer{

    @Override
    public void update(Observable observable, Object arg) {
        System.out.println("observable2 :" + observable + "arg2 :" + arg);
    }
}

TestObserver类的实现

package com.daming.java.observer;

public class TestObserver {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Observable observable = new Observable();
        MyObserver myObserver = new MyObserver();
        MyObserver2 myObserver2 = new MyObserver2();
        observable.addObserver(myObserver);
        observable.addObserver(myObserver2);

        observable.setChanged();
        observable.notifyObservers(14);

        observable.setChanged();
        observable.notifyObservers("I am daming");
    }
}

Log输入结果:

observable2 :com.daming.java.observer.Observable@14318bbarg2 :14
observable :com.daming.java.observer.Observable@14318bbarg :14
observable2 :com.daming.java.observer.Observable@14318bbarg2 :I am daming
observable :com.daming.java.observer.Observable@14318bbarg :I am daming

Java源码中上述代码中用的是推模式,当然源码中也有拉模式,即主动查询的模式。拉模式就像广播一样,通过onReceive()方法拉起来一些动作的,还有像ContentObserver可以通过拉模式,当数据库发生改变的时候,通过onChange()方法来调用一些操作。

—-接着我们来看看Android中异步的观察者模式。

ContentObserver就是异步的观察者模式,异步的观察者有什么好处呢?不阻塞观察者的回调。在同步通知中会有阻塞问题,各个Observer的响应方法是串行的,如果有一个observer耗时的话就会阻塞其他observer接收者了,这样就有可能就会引起bug来,所以在设计的时候多考虑一些,是否考虑用异步的观察者模式,让并发处理快一些;我们通过一个简单的demo来学习下异步的观察者模式:

先来看看Observer,这个Android中是抽象的类

package cn.daming.observer.design;

import android.os.Handler;
import android.util.Log;

public abstract class Observer {

    private Handler mHandler;

    public Observer(Handler handler) {
        mHandler = handler;
    }

    public void onChange() {
    }

    public final void dispatchChange() {
        Log.v("daming", "Observer dispatchChange is mHandler== null :" + (mHandler == null));
        if (mHandler == null) {
            onChange();
        } else {
            mHandler.post(new NotificationRunnable());
        }
    }

    private final class NotificationRunnable implements Runnable {

        @Override
        public void run() {
            Log.v("daming", "NotificationRunnable dispatchChange is run ... ");
            Observer.this.onChange();
        }
    }
}

接着来看看ObserverService这个类的实现:

package cn.daming.observer.design;

import java.util.ArrayList;
import java.util.List;

import android.util.Log;

public class ObserverService {

    private int mState;

    private List<Observer> mObservers = new ArrayList<Observer>();

    public final void registerObserver(Observer observer) {
        if (!mObservers.contains(observer)) {
            mObservers.add(observer);
        }
    }

    public final void unregisterObserver(Observer observer) {
        Log.v("daming", "ObserverService unregisterObserver :");
        mObservers.remove(observer);
    }

    public void notifyChange() {
        for (Observer observer : mObservers) {
            observer.dispatchChange();
        }
    }

    public int getState() {
        return mState;
    }

    public void setState(int state) {
        mState = state;
        notifyChange();
    }
}

最后我们来写测试类FirstActivity :

package cn.daming.observer.design;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.daming.designtraning.R;

public class FirstActivity extends Activity {

    private ObserverService mObserverService;
    private Button mButton;
    private int mState = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button) findViewById(R.id.button);

        mObserverService = new ObserverService();
        mObserverService.registerObserver(mFirstObserver);
        mObserverService.setState(++mState);


        mButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mObserverService.setState(++mState);
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mObserverService.unregisterObserver(mFirstObserver);

    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    private Observer mFirstObserver = new Observer(new Handler()) {

        @Override
        public void onChange() {
            int state = mObserverService.getState();
            Log.v("daming", "FirstObserver onChange is run state :" + state);
        }

    };
}

总结:通过Handler来实现异步的观察者模式,即构造Observer对象的时候传一个Handler的对象,这样在回调的时候,就用handler来发送异步的消息在主线程上来执行相应的操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

观察者模式--Java设计模式 的相关文章

随机推荐

  • Type-C接口简单介绍-面向单片机应用

    Type C接口简单介绍 面向单片机应用 1 绪论 用单片机做一些东西时 xff0c Type C接口逐渐替代了MicroUSB接口 但不像MicroUSB那样只有5V GND D 43 D ID五个接口 xff0c Type C接口有24
  • 嵌入式硬件:放大器电路仿真

    文章目录 说明同向放大电路反向放大电路放大器滤波电路低通滤波电路proteus仿真TINA TI仿真 窄带滤波电路preteus仿真TINA TI仿真 参考 说明 书上的放大电路图很多都是理论图 xff0c 和实际应用有所差异 比如下面这个
  • git 切换分支

    1 查看所有分支 git branch a 2 查看当前分支 号表示当前分支 git branch 3 切换分支 git checkout 39 分支名 39 4 修改代码仓库 git remote set url origin 39 仓库
  • 嵌入式安卓开发:使用Camera2获取相机

    文章目录 Camera2介绍Camera2的主要API类介绍CameraManager通过CameraManage获取Cameracharacteristics通过CameraManage获取CameraDevice从CameraDevic
  • ESP32的VSPI和HSPI

    说明 SPI共有4根线 xff0c MOSI MISO CS CLK xff0c 在ESP32中对应规则如下表 xff1a ESP32共有4个SPI xff0c 但是用户能够使用的只有2个SPI xff0c 分为VSPI和HSPI 引脚接口
  • Android Studio添加EasyPemissions

    问题描述 按照EasyPermissions主页描述的那样添加完依赖后 xff0c 在程序中使用还是报错 xff1a Failed to resolve pub devrel easypermissions 0 3 0 解决方法 首先 xf
  • ROS:话题编程 订阅者Subscriber的简单实现

    1 xff08 1 xff09 编写一个C 43 43 话题订阅者 该例程将订阅 turtle1 pose话题 xff0c 消息类型turtlesim Pose include lt ros ros h gt include 34 turt
  • 浅谈操作系统-启动过程

    前言 时光匆碌 xff0c 不知不觉都大三了 xff0c 在众多的专业课的学习中也算是找到了一些乐趣 xff0c 纸上得来终觉浅 xff0c 所以决定完整的回顾一下整个操作系统的知识 xff0c 为了理论与实践相结合 xff0c 以学校实验
  • 串口调试常见问题和排查方法

    串口UART作为嵌入式应用和通讯领域中最常用的接口之一 xff0c 接口协议虽然简单 xff0c 但在实际应用中不同设备之间的通讯也会存在各种小问题 xff0c 下面对使用中各种常见的问题做下总结和梳理 xff0c 可作为调试参考 串口可分
  • 3 POSIX 多任务及同步机制-拓展实验 条件变量与生产者-消费者问题

    3 POSIX 多任务及同步机制 拓展实验 条件变量与生产者 消费者问题 一 xff0e 实验目的 理解进程 线程同步问题 掌握POSIX条件变量机制的使用方法 深入理解在动态并发环境下 xff0c 进程 线程在运行过程中的资源竞争应发的问
  • 深度优先搜索DFS和广度优先搜索BFS

    相关博客链接 xff1a https www cnblogs com rjgcs p 5198467 html https blog csdn net xiaobo Clanguage article details 88085074 ht
  • 埋头努力之前得先看清方向

    埋头努力之前得先看清方向 写在工作半年 xff0c 第一次拿到绩效结果后 工作和学生时代最大的不同在于 xff0c 工作之后很多事情是消耗型的 xff0c 领导和组织看重的是输出 xff0c 而个人的成长和提升需要自己全权负责 这两者之间是
  • 周末写点轻松的吧

    一直觉得 有一段跟自己独处的时光是很幸福的事情 难得的双休日 xff0c 中午太阳很好 xff0c 照在绿萝上 xff0c 嫩嫩绿绿的叶子很漂亮 前几周去花市买了盆栀子花 xff0c 整整一大盆 xff0c 上面布满了花苞 以前见过开了花的
  • 为什么大部分的C/C++码农都成不了高级工程师?真实原因是缺少核心能力!

    一般来说技术团队的金字塔顶尖往往是技术最牛的人做底层架构师 xff08 或高级工程师 xff09 所以底层架构师在广大码农中的占比大概平均不到 20 然而80 码农干上许多年都是重复以下内容 xff0c 所以做不了架构师 xff0c 正在辛
  • kaggle邮箱不能验证+安装python的Speedml库

    注册kaggle账号遇到一些问题 下面是具体问题和解决方案 希望遇到同样问题的小伙伴不要再踩到坑啦 1kaggle邮箱不能验证You did not enter the correct captcha response Please try
  • 用程序验证生日“悖论”

    生日 悖论 其实并不是悖论 xff0c 它是说在一个人数超过23人的集体中 xff0c 至少有两个人生日在同一天的概率约为0 5 因为这个理论上的概率与人们的直觉不符 xff0c 才会被称为 悖论 我们可以用一个简单的小程序验证它哦 xff
  • python 中 defaultdict 的用法

    场景 xff1a 统计一个字符串列表中每个字符串的频数 一个明显的方法是建立一个键是字符串 xff0c 值是频数的字典 方法1 xff1a word count 61 for word in document if word in word
  • K近邻算法所面临的维数灾难问题

    K近邻算法的基本思想 K近邻算法是一种常用的监督学习方法 xff0c 其原理非常简单 xff1a 给定测试样本 xff0c 基于某种距离找出训练集中与其最靠近的K个训练样本 xff0c 然后基于这K个邻居的信息来进行预测 两个基本要素 xf
  • Android广播发送机制剖析【android广播系列二】

    上篇博客大致说了说广播的注册机制 xff0c 动态注册和静态注册广播的原理还不一样 xff0c 动态广播最后HashMap中了 xff0c 最后放到mReceiverResolver中 xff0c 以后当ActivityManagerSer
  • 观察者模式--Java设计模式

    观察者模式定义 xff1a 定义了对象之间的一对多的依赖 xff0c 这样一来 xff0c 当一个对象发生改变状态的时候 xff0c 它的所有依赖者都会收到通知并自动更新 参考如下图 xff1a 观察者设计模式也叫发布 订阅模式 也可以称作