首先看看JDK的Observer接口

  1. public interface Observer {
  2. void update(Observable o, Object arg);
  3. }

也就一个更新的方法,这里是要写自己要处理事情的逻辑(代码干活的地方)

然后就是Observable类,因为方法过多不好阅读,所以直接看大纲

方法大概就是设置改变状态,设置观察者,通知观察者等等....

我这里就说明下通知观察者的方法

  1. public void notifyObservers(Object arg) {
  2.  
  3. Object[] arrLocal;
  4.  
  5. synchronized (this) {
  6. if (!changed)
  7. return;
  8. arrLocal = obs.toArray();
  9. clearChanged();
  10. }
  11.  
  12. for (int i = arrLocal.length-1; i>=0; i--)
  13. ((Observer)arrLocal[i]).update(this, arg);
  14. }

简单点也就是去调用Observer接口的Update方法

弄懂这些就可以实现一个触发链模式了,代码如下(DNS解析的一个简单的实现)

执行图:

UML示例图:

观察者抽象:

  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. import java.util.Observable;
  4. import java.util.Observer;
  5. import java.util.Random;
  6.  
  7. /**
  8. * <p>既是观察者也是被观察者</p>
  9. *
  10. * @作者 five-five
  11. * @创建时间 2020/8/11
  12. */
  13. public abstract class DnsServer extends Observable implements Observer {
  14. //处理请求,也就是接收到事件后的处理
  15. @Override
  16. public void update(Observable o, Object arg) {
  17. Recorder recorder = (Recorder) arg;
  18. if (isLocal(recorder)) {
  19. recorder.setIp(generateIpAddress());
  20. } else {
  21. responsFromUpperServer(recorder);
  22. }
  23. sign(recorder);
  24. }
  25.  
  26. private String generateIpAddress() {
  27. Random random = new Random();
  28. return random.nextInt(255) + "." + random.nextInt(255) + "." + random.nextInt(255) + "." + "." + random.nextInt(255);
  29. }
  30.  
  31. void setUpper(DnsServer dnsServer) {
  32. super.deleteObservers();
  33. super.addObserver(dnsServer);
  34. }
  35.  
  36. private void responsFromUpperServer(Recorder recorder) {
  37. super.setChanged();
  38. super.notifyObservers(recorder);
  39. }
  40.  
  41. abstract void sign(Recorder recorder);
  42.  
  43. protected abstract boolean isLocal(Recorder recorder);
  44. }

观察者实现类:

  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. /**
  4. * @作者 five-five
  5. * @创建时间 2020/8/11
  6. */
  7. public class ChinaTopDnserver extends DnsServer {
  8. @Override
  9. void sign(Recorder recorder) {
  10. recorder.setOwner("中国");
  11. }
  12.  
  13. @Override
  14. protected boolean isLocal(Recorder recorder) {
  15. return recorder.getDomain().endsWith(".cn");
  16. }
  17. }
  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. /**
  4. * @作者 five-five
  5. * @创建时间 2020/8/11
  6. */
  7. public class SHDnserver extends DnsServer {
  8. @Override
  9. void sign(Recorder recorder) {
  10. recorder.setOwner("上海");
  11. }
  12.  
  13. @Override
  14. protected boolean isLocal(Recorder recorder) {
  15. return recorder.getDomain().endsWith(".sh");
  16. }
  17. }
  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. /**
  4. * @作者 five-five
  5. * @创建时间 2020/8/11
  6. */
  7. public class TopDnserver extends DnsServer {
  8. @Override
  9. void sign(Recorder recorder) {
  10. recorder.setOwner("全球");
  11. }
  12.  
  13. @Override
  14. protected boolean isLocal(Recorder recorder) {
  15. return true;
  16. }
  17. }

然后就是操作的实体类

  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. /**
  4. * @作者 five-five
  5. * @创建时间 2020/8/11
  6. */
  7. public class Recorder {
  8. //持有者
  9. private String owner;
  10.  
  11. //域名
  12.  
  13. private String domain;
  14. //IP地址
  15. private String ip;
  16. public Recorder() {
  17. }
  18.  
  19. public void setDomain(String domain) {
  20. this.domain = domain;
  21. }
  22.  
  23. public void setIp(String ip) {
  24. this.ip = ip;
  25. }
  26.  
  27. public void setOwner(String owner) {
  28. this.owner = owner;
  29. }
  30.  
  31. public String getOwner() {
  32. return owner;
  33. }
  34.  
  35. public String getDomain() {
  36. return domain;
  37. }
  38.  
  39. public String getIp() {
  40. return ip;
  41. }
  42.  
  43. @Override
  44. public String toString() {
  45. return "Recorder{" +
  46. "owner='" + owner + '\'' +
  47. ", domain='" + domain + '\'' +
  48. ", ip='" + ip + '\'' +
  49. '}';
  50. }
  51.  
  52. public Recorder(String domain, String ip) {
  53. this.domain = domain;
  54. this.ip = ip;
  55. }
  56. }

测试代码:

  1. package zen.design.pattern.creat.观察者模式.DNS解析;
  2.  
  3. /**
  4. * @作者 five-five
  5. * @创建时间 2020/8/11
  6. */
  7. public class Client {
  8. public static void main(String[] args) {
  9. DnsServer shdns = new SHDnserver();
  10. DnsServer cndns = new ChinaTopDnserver();
  11. DnsServer topdns = new TopDnserver();
  12. cndns.setUpper(topdns);
  13. shdns.setUpper(cndns);
  14. Recorder recorder = new Recorder();
  15. recorder.setDomain(".cf");
  16. shdns.update(null,recorder);
  17. System.out.println(recorder);
  18. }
  19. }

测试结果:

触发链模式之使用jdk的Observable和Observerver实现触发链模式(附JDK源码)的更多相关文章

  1. 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 百篇博客分析OpenHarmony源码 | v36.04

    百篇博客系列篇.本篇为: v36.xx 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CP ...

  2. 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析

    前面我们已经接触过几种数据结构了,有数组.链表.Hash表.红黑树(二叉查询树),今天再来看另外一种数据结构:栈.      什么是栈呢,我就不找它具体的定义了,直接举个例子,栈就相当于一个很窄的木桶 ...

  3. 自动化测试po模式是什么?自动化测试po分层如何实现?-附详细源码

    一.什么是PO模式 全称:page object model  简称:POM/PO PO模式最核心的思想是分层,实现松耦合!实现脚本重复使用,实现脚本易维护性! ​ 主要分三层: 1.基础层BaseP ...

  4. PHP伪造referer突破网盘禁止外链(附115源码)

    新建一个文件file.php.后面的参数就是需要伪造referfer的目标地址吧.如:file.php/http://www.xxx.xxx/xxx.mp3 复制内容到剪贴板 代码: <?$ur ...

  5. [区块链\理解BTCD源码]GO语言实现一个区块链原型

    摘要 本文构建了一个使用工作量证明机制(POW)的类BTC的区块链.将区块链持久化到一个Bolt数据库中,然后会提供一个简单的命令行接口,用来完成一些与区块链的交互操作.这篇文章目的是希望帮助大家理解 ...

  6. eclipse无法断点调试JDK源码的问题

    最近换了新版的eclipse,在jdk源码里面,打断点发现无法进入源码调试,程序直接跳过,已查资料发现自己eclipse配置的是jre环境的. 此处要配成jdk目录才有效 打开preferences, ...

  7. 曹工力荐:调试 jdk 中 rt.jar 包部分的源码(可自由增加注释,修改代码并debug)

    背景 大家知道,jdk安装的目录下,一般会有个src.zip包,这个包基本对应了rt.jar这个包.rt.jar这个包里面,就放了jdk中,jdk采用java实现的那部分类库代码,比如java.lan ...

  8. Mybatis源码手记-从缓存体系看责任链派发模式与循环依赖企业级实践

    一.缓存总览 Mybatis在设计上处处都有用到的缓存,而且Mybatis的缓存体系设计上遵循单一职责.开闭原则.高度解耦.及其精巧,充分的将缓存分层,其独到之处可以套用到很多类似的业务上.这里将主要 ...

  9. 设计模式(十八)——观察者模式(JDK Observable源码分析)

    1 天气预报项目需求,具体要求如下: 1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方). 2) 需要设计开放型 API,便于其他第三方也能接入气象 ...

随机推荐

  1. Linux下Storm2.1.0的伪分布式安装

    官方下载网址:http://storm.apache.org/downloads.html 1.第一步我们先从官网下载解压包  2.然后进行解压 3.配置环境变量 在profile里面插入如下格式语句 ...

  2. IDEA 格式化代码快捷键

    一般都是:Ctrl+Alt+L 如果未格式化的话,可能与以下软件的快捷键冲突了: QQ 网易云 也可能是其他的快捷键组合,具体可查看工具栏Code->Reformat Code: 也可重新设置i ...

  3. Intelij DataGrip 的安装和使用

    链接: Intelij DataGrip 安装教程以及汉化教程 Intelij DataGrip 使用教程 以上两个教程已使用过,没有问题 如有侵权请联系删除

  4. TLV通信协议

    基础 TLV协议是BER编码的一种,全称是Tag.length.value.该协议简单高效,能适用于各种通信场景,且具有良好的可扩展性.TLV协议的基本格式如下: 其中,Tag占2个字节,是报文的唯一 ...

  5. Python如何向SQLServer存储二进制图片

    需求是需要用python往 SqlServer中的image类型字段中插入二进制图片 核心代码,研究好几个小时的代码: 安装pywin32,adodbapi image_url = "图片链 ...

  6. php必须掌握的常用函数

    数学函数 数组函数 字符串函数

  7. DJANGO-天天生鲜项目从0到1-002-用户模块-注册

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  8. git上传本地项目到gitlab

    <1>输入git config --global user.name "你的用户名" <2>输入git config --global user.email ...

  9. goroutine间的同步&协作

    Go语言中的同步工具 基础概念 竞态条件(race condition) 一份数据被多个线程共享,可能会产生争用和冲突的情况.这种情况被称为竞态条件,竞态条件会破坏共享数据的一致性,影响一些线程中代码 ...

  10. 10-Pandas之数据融合(pd.merge()、df.join()、df.combine_first()详解)

    一.pd.merge() pd.merge()的常用参数 参数 说明 left 参与合并的左侧DataFrame right 参与合并的右侧DataFrame how 如何合并.值为{'left',' ...