17、Observer 观察者模式
以一个实例给大家引入观察者,大家多多少少都写过html或者java中的swing。我们定义一个按钮,给他增加一个点击事件,那么这个方法是怎么被触发到呢,对了,就是利用了观察者设计模式
观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
介绍
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优点: 1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
实例代码
package com.mashibing.dp.observer.v9;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Button b = new Button();
b.addActionListener(new MyActionListener());
b.addActionListener(new MyActionListener2());
b.buttonPressed();
}
}
class Button {
private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
public void buttonPressed() {
ActionEvent e = new ActionEvent(System.currentTimeMillis(),this);
for(int i=0; i<actionListeners.size(); i++) {
ActionListener l = actionListeners.get(i);
l.actionPerformed(e);
}
} public void addActionListener(ActionListener l) {
actionListeners.add(l);
}
} interface ActionListener {
public void actionPerformed(ActionEvent e);
} class MyActionListener implements ActionListener { public void actionPerformed(ActionEvent e) {
System.out.println("button pressed!");
} } class MyActionListener2 implements ActionListener { public void actionPerformed(ActionEvent e) {
System.out.println("button pressed 2!");
} } class ActionEvent { long when;
Object source; public ActionEvent(long when, Object source) {
super();
this.when = when;
this.source = source;
} public long getWhen() {
return when;
} public Object getSource() {
return source;
} }
运行结果如下:
button pressed!button pressed 2!
package com.mashibing.dp.observer.v9;
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestFrame extends Frame {
public void launch() {
Button b = new Button("press me");
b.addActionListener(new MyActionListener());
b.addActionListener(new MyActionListener2());
this.add(b);
this.pack();
this.addWindowListener(new WindowAdapter(){ @Override
public void windowClosing(WindowEvent e) {
System.exit(0);
} });
this.setLocation(400, 400);
this.setVisible(true);
} public static void main(String[] args) {
new TestFrame().launch();
} private class MyActionListener implements ActionListener { //Observer @Override
public void actionPerformed(ActionEvent e) {
((Button)e.getSource()).setLabel("press me again!");
System.out.println("button pressed!");
} } private class MyActionListener2 implements ActionListener { @Override
public void actionPerformed(ActionEvent e) {
System.out.println("button pressed 2!");
} }
}
总结
相比较与观察者模式,我们或许有许多获取另外一个对象状态的方式,比如,常见的轮询方式,或者仅仅在需要的时候去查一下对方的状态等,不过观察者模式有其特殊的用途,而且更加灵活。
该模式原理比较简单直接,但是实际使用过程中需要考虑一些细节问题:
何时通知?
有谁触发通知?
观察者是关注状态变化的次数还是最终的状态?
如果消息通知被阻塞,应该怎么办?
是否可以改为异步消息通知?
上面这些都是实际使用时应该考虑的。考虑清楚这些细节才能更灵活的应用该模式解决实际问题。
公众号:发哥讲
这是一个稍偏基础和偏技术的公众号,甚至其中包括一些可能阅读量很低的包含代码的技术文,不知道你是不是喜欢,期待你的关注。
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~
● 扫码关注我们
据说看到好文章不推荐的人,服务器容易宕机!
本文版权归发哥讲和博客园共有,原创文章,未经允许不得转载,否则保留追究法律责任的权利。
17、Observer 观察者模式的更多相关文章
- C++设计模式-Observer观察者模式
Observer观察者模式作用:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己 UML图: S ...
- Observer 观察者模式
简介 观察者模式(Observer),有时又被称为[发布]publish-[订阅]Subscribe模式.模型-视图(View)模式.源-收听者(Listener)模式或从属者模式.在此种 ...
- 委托、事件、Observer观察者模式的使用解析二
一.设计模式-Observer观察者模式 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新.Observer模式是一种 ...
- Observer观察者模式与OCP开放-封闭原则
目录 场景引入 在联网坦克项目中使用观察者模式 总结 在学习Observer观察者模式时发现它符合敏捷开发中的OCP开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向Observer模式迈进, ...
- Observer 观察者模式 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 设计模式18:Observer 观察者模式(行为型模式)
Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...
- java设计模式解析(1) Observer观察者模式
设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...
- observer观察者模式
观察者模式(有时又被称为发布-订阅Subscribe>模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生变化时,会通知所有观察者对象,让 ...
- 设计模式 ( 十七 ):Observer 观察者模式 -- 行为型
1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来说,当某个对象的状态发生改变时,你仍然需要对象之间能互相通信.但是 ...
随机推荐
- java 面向对象(九):类的结构:构造器(一)简介;属性赋值顺序;JavaBean的概念
1.构造器(或构造方法):Constructor构造器的作用: * 1.创建对象 * 2.初始化对象的信息2.使用说明: * 1.如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器 * 2 ...
- Python之协程、异步IO、redis缓存、rabbitMQ队列
本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...
- CentOS 无法加载 ntfs文件系统类型解决办法
问题: CentOS无法加载ntfs 文件系统类型的移动硬盘. 解决办法: 1.下载rpmforge,下载对应的版本.(对应的CentOS版本,并区分32位和64位). 例如: wget http:/ ...
- CentOS8.0 Docker Repository
一.硬件软件准备 1.2台服务器或者电脑(使用云服务器1.阿里云 2.百度云各一台) ,系统均为CentOS 8.0 2.分别安装Docker 3.测试镜像准备(准备的是 ...
- ffmpeg拉流长时间堵塞解决方式
由于网络堵塞或者推流端错误导致拉流端没有流数据,ffmpeg主要会堵塞两个函数,直到下次流数据的到来 avformat_open_input() 该函数是在打开流数据时,如果没有这个流的ip,http ...
- 计算思维(Computational Thinking)在少儿编程中的体现
本文主要针对少儿编程从业人员及正在学习编程的学生家长 大家好,我是C大叔,国内早期的少儿编程从业人员.一直以来都是在做scratch,JavaScript,python以及信息学奥赛C++的讲师,教研 ...
- css属性inline-block的应用
1. 让两个块级元素处于同一行 2. 需要元素撑开边框的时候
- 完全卸载MySQL完整图文流程
想把mlsql卸载了重装,看了许多文章试了很多方法都没办法完全卸载,直到看到了这篇文章, 可以完全卸载mysql,在这里谢谢博主,也拿出来分享给大家 原文链接:https://blog.csdn.ne ...
- 【新生学习】深度学习与 PyTorch 实战课程大纲
各位20级新同学好,我安排的课程没有教材,只有一些视频.论文和代码.大家可以看看大纲,感兴趣的同学参加即可.因为是第一次开课,大纲和进度会随时调整,同学们可以随时关注.初步计划每周两章,一个半月完成课 ...
- 基于Bilateral Attention和Pyramid Filling Block的图像修复方法
One-Stage Inpainting with Bilateral Attention and Pyramid Filling Block 论文链接:https://arxiv.org/abs/1 ...