head frist 设计模式学习之 JVM中的博物馆奇妙夜(观察者模式)
博物馆奇妙夜! 博物馆奇妙夜!博物馆奇妙夜!
重说三!!!
JVM看了《博物馆奇妙夜》电影之后,决定在自己家里开一个博物馆!毕竟需要什么new一下就好,博物馆很快就
开起来了,并且任命你为馆长(金馆长?),并且郑重的告诉了你作为馆长的职责:
1.接受JVM的节目单。
2.通知博物馆里的对象准备节目。
作为一名骄傲的oo程序员,你怎么能亲力亲为做这种事呢?于是你准备招一个下属,在java的世界里,你知道只需要new
一个就好,但是new之前需要一个class,没关系,写一个!
于是你看了一下节目单,有猴子,老鼠,和 橡皮鸭的节目,那么,do it!
class worker
{
private String program_card;
public void program_cardChanged( )// 当节目单改变时调用此方法,这里不用管是如何调用的。
{
String program_card=getProgram_card(); // 这里假设已经实现好了
monkey.setProgram(program_card); //把节目单给猴子,以下同理
mouse.setProgram(program_card);
ruberDuck.setProgram(program_card);
}
//其他方法。。。。
}
看起来这是一个很棒的下属,第一天的工作完成的非常棒!你开心的做别的事儿去了(LOL?),第二天两个电话打了进来
第一个是JVM打来的,他责备你:今天toy soldier的节目为什么没有上?
第二个是ruberDuck打来的,它向你抱怨:今天我不想演节目,干嘛给我节目单?
你怒气冲冲的找来你的worker ,大骂它一顿!但是它也很委屈,跟你说:
"我都是按照你写的来的啊,要错也是你错!"
你意识到可能是你错了,但是作为老板你是不会承认的,并且,你决定重新雇佣(new)一个工人,在这之前,我们先看看
第一个工人都犯了些什么错。
1.没有针对接口/超类编程,而是针对实现编程,导致当表演人员发生变化时,必须修改program_cardChanged()方法来应对
变化。
2.没有将变化封装。
3.monkey,mouse,ruberDuck等类都有setProgram( String program_card)方法,好像可以统一成接口。
是时候引入今天的主角了!
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并
自动更新。
很明显,换到当前环境下就是:当worker对象中的program_card发生改变时,所有的想表演节目的对象都会接受
通知。
在解决上面的三个问题之前,我们先确定依赖:
在被依赖的对象(被观察者/主题)中,声明一个arraylist,用来存储依赖者(观察者)的实例,存储的过程我们称之为
注册(register)。
好了,我们正式开始oo设计!
1.设计被观察者接口。
通过上面的分析,我们知道被观察者需要具备的功能:注册,解注册和通知观察者,那么:
public interface Subject // 主题/被观察者
{
public void registObserver(Observer o); //注册
public void removeObserver(Observer o); //解注册
public void notifyObservers(); //通知
}
2.设计观察者接口
这里只需要一个方法供被观察者调用就好。
public interface Observer
{
public void setProgram(String Program_card);
}
你让新招来的工人实现Subject:
public class Worker implements Subject
{
private Arraylist<Observer> observers;
private String program_card;
public Worker()
{
observers = new Arralisy<Observer> ();
}
public registerObserver(Observer o) //注册的过程就是将对象放到arraylist里
{
observers.add(o);
}
public removeObserver(Observer o) //解注册过程
{
int i=observers.indexOf(o);
if(i>=0)
{
observers.remove(i);
}
}
public void notifyObservers() //遍历list,通知观察者
{
for(int i=0;i<observer,size();i++)
{
Observer o=observers.get(i);
o.setProgram(program_card);
}
}
public void program_cardChanged()
{
notifyObservers(); //当节目单更新时,通知观察者
}
}
让博物馆的演员们实现Observer,例如,RuberDuck:
public class RuberDuck implements Observer
{
private String program_card;
private Subject worker;
public RuberDuck(Subject worker)
{
this.worker=worker;
work.registerObserver();
}
public void setProgram(string program_card)
{
this.program_card=program_card;
}
//其他方法省略。。。。。
}
一切看起来都是没问题的
但是观察者模式到底为我们做了些什么呢?
答案 :松耦合
在观察者模式中,被观察者只需要知道观察者实现了Observer接口,并不知道观察者本身是什么,所以,我们可以独立的使用观察者(即复用)
而不用将两者捆绑在一起(紧耦合),反之,观察者也是如此。
作为一名oo程序员,你一定又发现了一个问题!那就是 String Program_card!既然是松耦合,那被观察者为什么知道观察者需要的数据类型呢?
对的,事实上被观察者不应该知道具体的数据类型,在java内置的观察者模式中,传递的数据类型是object,这样更符合我们松耦合的设定。
另外,从java内置的观察者模式中我们还可以对我们的观察者模式进行完善。
1.change。在我们的观察者模式中,只要数据一改变,就会通知所有的观察者,但有时候我们并不需要这么“灵敏”,所以可以在类中加入一个
改变位,当改变位=true 时,再通知观察者。(java内置的有相应的setChange和hasChange方法)。
2.推和拉。我们的观察者是采取推的方式传递数据,而拉则是 让 被观察者提供get方法,让观察者接到通知的时候去get,这两种方法各有利弊,
不再赘述。(同样,java内置的都有实现)
博主功力尚浅,博文中如有不当之处请读者海涵。
head frist 设计模式学习之 JVM中的博物馆奇妙夜(观察者模式)的更多相关文章
- 设计模式学习笔记——java中常用的设计模式
单例设计模式(Singleton Pattern) 观察者模式(Observer Pattern) 工厂模式(Factory Pattern) 策略模式(Strategy Pattern) 适配器模式 ...
- 学习一下 JVM (二) -- 学习一下 JVM 中对象、String 相关知识
一.JDK 8 版本下 JVM 对象的分配.布局.访问(简单了解下) 1.对象的创建过程 (1)前言 Java 是一门面向对象的编程语言,程序运行过程中在任意时刻都可能有对象被创建.开发中常用 new ...
- JVM中ClassLoader的学习
JVM中class loaderの学习 一..class文件和jvm的关系 类的加载 所有的编译生成的.class文件都会被直接加载到JVM里面来吗(并不 首先我们明确一个概念,.class文件加载到 ...
- JVM调优学习 【更新中】
JVM调优(jdk1.8) 老生常谈,面试吹牛的的最佳谈资,在接下来的几天里,我找了点资料来对其进行一波学习: 本地环境是不需要对我们的虚拟机进行优化的,一般在生产环境下,也就是Linux下才有对JV ...
- 设计模式学习(二十四):Spring 中使用到的设计模式
设计模式学习(二十四):Spring 中使用到的设计模式 作者:Grey 原文地址: 博客园:设计模式学习(二十四):Spring 中使用到的设计模式 CSDN:设计模式学习(二十四):Spring ...
- 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期
一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...
- Synchronized 和 Lock 锁在JVM中的实现原理以及代码解析
一.深入JVM锁机制:synchronized synrhronized关键字简洁.清晰.语义明确,因此即使有了Lock接口,使用的还是非常广泛.其应用层的语义是可以把任何一个非null对象作为&qu ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- 设计模式学习--Singleton
What Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点. Why Singletion是我比较熟悉的设计模式之一,在平常的开发过程中,也曾几次用到,它主要适用于如下场景: ...
随机推荐
- Makefile隐含规则和用到的默认变量
如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则.那么,make会试图去自动推导产生这个目标的规则和命令,如果make可以自动推导生成这个目标的规则和命令,那么这个行为就是隐 ...
- 原生js的兼容问题总结
获取元素的非行间样式 function getStyle(obj, name) { //获取元素的非行间样式 if (obj.currentStyle) { return obj.currentSty ...
- C#事件作用和用法
例如有下面的需求需要实现:程序主画面中弹出一个子窗口.此时主画面仍然可以接收用户的操作(子窗口是非模态的).子窗口上进行某些操作,根据操作的结果要在主画面上显示不同的数据. 即如下图所示: 大多数我们 ...
- Hibernate持久化对象
持久化类应遵循的规则: 有无参构造器,构造器的修饰符>=默认访问控制符 有标识属性,映射数据库表的主键,建议使用基本类型的包装类 每个成员有setter和getter 非final修饰的类 重写 ...
- javascript 写状态模式
写了状态模式的切换,以及分支循环.but 怎么实现子状态嵌套呢? /** * by JackChen 2016-3-26 11.51.20 * * 状态模式: * 一个状态到另一个状态的变换.其实可以 ...
- 破解https和https原理
http://blog.csdn.net/cch5487614/article/details/6364711 http://www.jb51.net/network/68135.html
- HTML新元素
<canvas> 标签定义图形,比如图表和其他图像.该标签基于 JavaScript 的绘图 API <audio> 定义音频内容 <video> 定义视频(vid ...
- Activity组件的UI实现
Activity组件的UI实现需要与WindowManagerService服务和SurfaceFlinger服务进行交互 1. Activity组件在启动完成后,会通过一个类型为Session的Bi ...
- 定时工作方式2实现1s定时
定时器的几种工作方式中,除0和前面的1类似都需要初始化计数值,然后开始计数,计数溢出后,需要再次控制计数的初值,但工作模式2不同于此,工作方式2将THx和TLx分开处理,将初值存放在THx中,计数时只 ...
- Morgan stanley 电话面试
首先是聊项目, 不会涉及到具体的技术问题 1.C和C++的区别:C++里的RTTI 2.vector 和 list的区别 : casting operator ; smart pointer. 3.数 ...