Java设计模式开发中使用观察者模式的实例教程
作者:匆忙拥挤repeat 发布时间:2021-06-22 15:54:19
标签:Java,设计模式,观察者模式
观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也不同,讲述方式也不近相同。
关键要素
主题:
主题是观察者观察的对象,一个主题必须具备下面三个特征。
持有监听的观察者的引用
支持增加和删除观察者
主题状态改变,通知观察者
观察者:
当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。
为什么要用这种模式
这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。
松耦合
观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。
Java实现观察者模式
1. Java自带的实现
类图
/**
* 观察目标 继承自 java.util.Observable
* @author stone
*
*/
public class UpdateObservable extends Observable {
private int data;
public UpdateObservable(Observer observer) {
addObserver(observer);
/*
* add other observer
*/
}
public int getData() {
return data;
}
public void setData(int data) {
if (data != this.data) {
this.data = data;
setChanged(); //标记 改变, 只有标记后才能通知到
notifyObservers(); //通知
}
}
@Override
public synchronized void addObserver(Observer o) {
super.addObserver(o);
}
@Override
public synchronized void deleteObserver(Observer o) {
super.deleteObserver(o);
}
@Override
public void notifyObservers() {
super.notifyObservers();
}
@Override
public void notifyObservers(Object arg) {
super.notifyObservers(arg);
}
@Override
public synchronized void deleteObservers() {
super.deleteObservers();
}
@Override
protected synchronized void setChanged() {
super.setChanged();
}
@Override
protected synchronized void clearChanged() {
super.clearChanged();
}
@Override
public synchronized boolean hasChanged() {
return super.hasChanged();
}
@Override
public synchronized int countObservers() {
return super.countObservers();
}
}
/**
* 观察者 实现 java.util.Observer接口
* @author stone
*
*/
public class UpdateObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("接收到数据变化的通知:");
if (o instanceof UpdateObservable) {
UpdateObservable uo = (UpdateObservable) o;
System.out.print("数据变更为:" + uo.getData());
}
}
}
2. 自定义的观察模型
类图
/**
* 抽象观察者 Observer
* 观察 更新
* @author stone
*
*/
public interface IWatcher {
/*
* 通知接口:
* 1. 简单通知
* 2. 观察者需要目标的变化的数据,那么可以将目标用作参数, 见Java的Observer和Observable
*/
// void update(IWatched watched);
void update();
}
/**
* 抽象目标 Subject
* 提供注册和删除观察者对象的接口, 及通知观察者进行观察的接口
* 及目标 自身被观察的业务的接口
* @author stone
*
*/
public interface IWatchedSubject {
public void add(IWatcher watch);
public void remove(IWatcher watch);
public void notifyWhatchers();
public void update();//被观察业务变化的接口
}
/**
* 具体观察者 Concrete Observer
*
* @author stone
*
*/
public class UpdateWatcher implements IWatcher {
@Override
public void update() {
System.out.println(this + "观察到:目标已经更新了");
}
}
/**
* 具体目标角色 Concrete Subject
* @author stone
*
*/
public class UpdateWatchedSubject implements IWatchedSubject {
private List<IWatcher> list;
public UpdateWatchedSubject() {
this.list = new ArrayList<IWatcher>();
}
@Override
public void add(IWatcher watch) {
this.list.add(watch);
}
@Override
public void remove(IWatcher watch) {
this.list.remove(watch);
}
@Override
public void notifyWhatchers() {
for (IWatcher watcher : list) {
watcher.update();
}
}
@Override
public void update() {
System.out.println("目标更新中....");
notifyWhatchers();
}
}
* 是观察者的一种实现:
类图
/**
* 监听 用户在注册后
* @author stone
*
*/
public interface IRegisterListener {
void onRegistered();
}
/**
* 监听 当用户登录后
* @author stone
*
*/
public interface ILoginListener {
void onLogined();
}
/*
* * 是观察者模式的一种实现
* 一些需要监听的业务接口上添加 * ,调用 * 的相应方法,实现监听
*/
public class User {
public void register(IRegisterListener register) {
/*
* do ... register
*/
System.out.println("正在注册中...");
//注册后
register.onRegistered();
}
public void login(ILoginListener login) {
/*
* do ... login
*/
System.out.println("正在登录中...");
//登录后
login.onLogined();
}
}
/**
* 观察者(Observer)模式 行为型模式
* 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时观察某一个目标对象。
* 这个目标对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己
* 目标对象中需要有添加、移除、通知 观察者的接口
*
* @author stone
*/
public class Test {
public static void main(String[] args) {
/*
* 使用Java自带的Observer接口和Observable类
*/
UpdateObservable observable = new UpdateObservable(new UpdateObserver());
observable.setData(99);
System.out.println("");
System.out.println("");
/*
* 自定义的观察者模型
*/
IWatchedSubject watched = new UpdateWatchedSubject();
watched.add(new UpdateWatcher());
watched.add(new UpdateWatcher());
watched.update();
System.out.println("");
/*
* 子模式- *
*/
User user = new User();
user.register(new IRegisterListener() {
@Override
public void onRegistered() {
System.out.println("监听到注册后。。。");
}
});
user.login(new ILoginListener() {
@Override
public void onLogined() {
System.out.println("监听到登录后。。。");
}
});
}
}
打印
接收到数据变化的通知:
数据变更为:99
目标更新中....
observer.UpdateWatcher@457471e0观察到:目标已经更新了
observer.UpdateWatcher@5fe04cbf观察到:目标已经更新了
正在注册中...
监听到注册后。。。
正在登录中...
监听到登录后。。。


猜你喜欢
- 实例如下:using System;using System.Linq.Expressions;class DynamicPredicate
- 本文汇总了C#启动外部程序的几种常用方法,非常具有实用价值,主要包括如下几种方法:1. 启动外部程序,不等待其退出。2. 启动外部程序,等待
- 茫茫人海千千万万,感谢这一秒你看到这里。希望我的面试题系列能对你的有所帮助!共勉!愿你在未来的日子,保持热爱,奔赴山海!Java基础知识(继
- 背景Android开发中,加载图片过多、过大很容易引起OutOfMemoryError异常,即我们常见的内存溢出。因为Android对单个应
- 目录Java 的Stream流一、定义二、操作的特征三、代码示例1、生成流2、forEach 迭代3、limit方法用于获取指定数量的流4、
- 这篇文章主要介绍了Java多线程的临界资源问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- Elastic Search是一个开源的,分布式,实时搜索和分析引擎。Spring Boot为Elasticsearch及Spring Da
- 在Java中当try、finally语句中包含return语句时,执行情况到底是怎样的,finally中的代码是否执行,大家众说纷纭,有的说
- MyBatis提供了 * 接口,我们可以实现自己的 * ,将其作为一个plugin装入到SqlSessionFactory中。 首先要说的是
- 数字可以标志货币、百分比、积分和电话号码等,就货币而言,在不同的国家会以不同的格式来定义,本实例将接收用户输入的数字,然后在控制台中输出其货
- 本文介绍了Android Studio 超级简单的打包生成apk,分享给大家,也给自己留个笔记。为什么要打包:apk文件就是一个包,打包就是
- 1.背景选择器(位于res/drawable/,使用方法:android:background=”@drawable/XXX”) <?
- Java集合ArrayDeque类实例分析前言ArrayDeque类是双端队列的实现类,类的继承结构如下面,继承自AbastractColl
- 本文实例讲述了C#画笔Pen绘制光滑模式曲线的方法。分享给大家供大家参考。具体实现方法如下:using System;using Syste
- 1. RSA加密与解密 -- 使用公钥加密、私钥解密public class RSATool { &nb
- 熬夜写完,尚有不足,但仍在努力学习与总结中,而您的点赞与关注,是对我最大的鼓励!在一些本地化项目开发当中,存在这样一种需求,即开发完成的项目
- 一、使用 System.Xml.Serialization类1、定义元数据引入System.Xml.Serialization命名空间。XM
- 如何快速判断一个元素是不是在一个集合里?这个题目是我最近面试的时候常问的一个问题,这个问题不同人都有很多不同的回答。今天想介绍一个很少有人会
- 接收JSON浏览器传来的参数,可以是 key/value 形式的,也可以是一个 JSON 字符串。在 Jsp/Servlet 中,我们接收
- 前言:GraphQL既是API查询语言,也是使用当前数据执行这些查询的运行时。GraphQL让客户能够准确地要求他们所需要的东西,仅此而已,