博物馆奇妙夜! 博物馆奇妙夜!博物馆奇妙夜!
重说三!!!
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中的博物馆奇妙夜(观察者模式)的更多相关文章

  1. 设计模式学习笔记——java中常用的设计模式

    单例设计模式(Singleton Pattern) 观察者模式(Observer Pattern) 工厂模式(Factory Pattern) 策略模式(Strategy Pattern) 适配器模式 ...

  2. 学习一下 JVM (二) -- 学习一下 JVM 中对象、String 相关知识

    一.JDK 8 版本下 JVM 对象的分配.布局.访问(简单了解下) 1.对象的创建过程 (1)前言 Java 是一门面向对象的编程语言,程序运行过程中在任意时刻都可能有对象被创建.开发中常用 new ...

  3. JVM中ClassLoader的学习

    JVM中class loaderの学习 一..class文件和jvm的关系 类的加载 所有的编译生成的.class文件都会被直接加载到JVM里面来吗(并不 首先我们明确一个概念,.class文件加载到 ...

  4. JVM调优学习 【更新中】

    JVM调优(jdk1.8) 老生常谈,面试吹牛的的最佳谈资,在接下来的几天里,我找了点资料来对其进行一波学习: 本地环境是不需要对我们的虚拟机进行优化的,一般在生产环境下,也就是Linux下才有对JV ...

  5. 设计模式学习(二十四):Spring 中使用到的设计模式

    设计模式学习(二十四):Spring 中使用到的设计模式 作者:Grey 原文地址: 博客园:设计模式学习(二十四):Spring 中使用到的设计模式 CSDN:设计模式学习(二十四):Spring ...

  6. 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期

    一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...

  7. Synchronized 和 Lock 锁在JVM中的实现原理以及代码解析

    一.深入JVM锁机制:synchronized synrhronized关键字简洁.清晰.语义明确,因此即使有了Lock接口,使用的还是非常广泛.其应用层的语义是可以把任何一个非null对象作为&qu ...

  8. Java设计模式学习记录-GoF设计模式概述

    前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...

  9. 设计模式学习--Singleton

    What Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点. Why Singletion是我比较熟悉的设计模式之一,在平常的开发过程中,也曾几次用到,它主要适用于如下场景: ...

随机推荐

  1. mongodb 安装及,设置账户、主从

    我原来没用过mongodb ,在晚上查了查需要的命令,关于怎么mongodb怎么用,我就不知道了 官方网站: http://www.mongodb.org/ MongoDB 安裝,主从配置一 Mong ...

  2. 每天一条linux命令——crontab

    crontab命令被用来提交和管理用户的需要周期性执行的任务,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查 ...

  3. android BitmapFacty.Options的用法

    通常我们在开发android应用程序时,在加载图片时常常需要与Bitmap打交道,一般会使用BitmapFactory中提供的相关decode方法获取: 如果一张很大的图片,我们不加处理直接decod ...

  4. SQL 添加字段和默认值脚本

    --插入字段和默认值alter table Acc_WayBill add DeclaredValue nvarchar(50)goEXEC sys.sp_addextendedproperty @n ...

  5. rownum

    rownum是一个伪列,oracle数据库会对查找到的数据 从1 开始递增指定每行的rownum值, 当查询条件里有 rownum时(比如 where rownum>2),数据库会依次从数据集里 ...

  6. PHP trim去空格函数

    trim() 能除去的字符有“ ”空格."\t"水平制表符."\n"换行符."\r"回车符."\0字符串结束符".&qu ...

  7. OS概论2

    实时系统 实时即表示及时,实时计算可以定义为这样一类计算:系统的正确性,不仅由计算的逻辑结果来确定,而且还取决于产生结果的时间.事实上,实时系统最主要的特征,是将时间作为关键参数,它必须对所接收到的某 ...

  8. 【WPF】Dispatcher及线程操作

    WPF 应用程序启动后,会有两个线程: 1. 一个是用来处理UI呈现(处理UI的请求,比如输入和展现等操作). 2. 一个用来管理 UI的 (对UI元素及整个UI进行管理). 像Winform一样,W ...

  9. Leaflet学习笔记-Leaflet.awesome-markers

    基础篇传送门 http://www.cnblogs.com/CoffeeEddy/p/4919987.html 效果图 是不是感觉很美观啊 为什么选择awesome 地图上面需要各种各样的Mark,难 ...

  10. Android Camera 预览图像被拉伸变形的解决方法【转】

    问题描述: 预览图像被拉伸变形 问题原因: 由于预览图像大小跟SurfaceView 大小不一致引起 解决方法: 获取系统支持的所有预览尺寸[getSupportedPictureSizes],然后再 ...