以一个实例给大家引入观察者,大家多多少少都写过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 观察者模式的更多相关文章

  1. C++设计模式-Observer观察者模式

    Observer观察者模式作用:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己 UML图: S ...

  2. Observer 观察者模式

    简介       观察者模式(Observer),有时又被称为[发布]publish-[订阅]Subscribe模式.模型-视图(View)模式.源-收听者(Listener)模式或从属者模式.在此种 ...

  3. 委托、事件、Observer观察者模式的使用解析二

    一.设计模式-Observer观察者模式 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新.Observer模式是一种 ...

  4. Observer观察者模式与OCP开放-封闭原则

    目录 场景引入 在联网坦克项目中使用观察者模式 总结 在学习Observer观察者模式时发现它符合敏捷开发中的OCP开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向Observer模式迈进, ...

  5. Observer 观察者模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. 设计模式18:Observer 观察者模式(行为型模式)

    Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...

  7. java设计模式解析(1) Observer观察者模式

      设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...

  8. observer观察者模式

    观察者模式(有时又被称为发布-订阅Subscribe>模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生变化时,会通知所有观察者对象,让 ...

  9. 设计模式 ( 十七 ):Observer 观察者模式 -- 行为型

    1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来说,当某个对象的状态发生改变时,你仍然需要对象之间能互相通信.但是 ...

随机推荐

  1. Apache Kylin v3.1.0 重点功能推介

    Apache Kylin v3.1.0 已于上周正式发布,其中包含了许多值得一试的新功能,本文选择了 Presto 查询下压引擎.Flink 构建引擎.Kylin on Kubernetes 解决方案 ...

  2. 静态代理,动态代理和CGLIB代理模式

    代理模式 一.概述 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目 ...

  3. 一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~

    前言 公司有一个 Web 管理系统,使用 Tomcat 进行部署.由于是后台管理系统,所有的网页都需要登录授权之后才能进行相应的操作. 起初这个系统的用的人也不多,为了节省资源,这个系统仅仅只是单机部 ...

  4. Shell基本语法---处理海量数据的grep命令

    grep命令 shell脚本三剑客之一 grep应用场景:通常对数据进行 行的提取 语法:grep [选项] [内容] [file] -v 对内容进行取反提取 -n 对提取的内容显示行号 -w 精确匹 ...

  5. 阿里云的maven仓库

    自从开源中国的maven仓库挂了之后就一直在用国外的仓库,慢得想要砸电脑的心都有了.如果你和我一样受够了国外maven仓库的龟速下载?快试试阿里云提供的maven仓库,从此不在浪费生命…… 仓库地址: ...

  6. Python for循环学习总结笔记

    循环是任何语⾔的⼀个必备要素.同样地,for循环就是Python的⼀个重要组成部分.然而还有⼀些内容是初学者常常忽视的.下面是Python for循环学习总结笔记,一起来查漏补缺吧!         ...

  7. Cordova iPhone 刘海屏 和 安卓瀑布屏 等异形屏幕的适配处理

    1.  在cordova项目的config.xml中指定StatusBarOverlaysWebView(需要cordova-plugin-statusbar插件支持),表示应用界面是否覆盖状态栏(系 ...

  8. 如何查看预收录在arXiv上论文的LaTeX源文件并编译

    arXiv 是一个收集物理学.数学.计算机科学与生物学论文预印本的网站. 对于理科生来说,经常需要在上面搜索下载一些论文,正常情况下,一般人下载的只是 pdf 文件,其实可以在 arXiv 上下载编译 ...

  9. python3 httpConnection——post请求

    #coding=utf-8 import http.clientimport urllib.parse #与服务器建立链接url = 'code.ali.cn:80' conn = http.clie ...

  10. 在CentOS 7 上为docker配置端口转发以兼容firewall

    在CentOS 7上当我们以类似下列命令将主机端口与容器端口映射时可能遇到无法访问容器服务的问题 docker run --name web_a -p 192.168.1.250:803:80 -d ...