博物馆奇妙夜! 博物馆奇妙夜!博物馆奇妙夜!
重说三!!!
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. Linux网络应用编程之Packet Tracer安装及界面介绍

    Packet Tracer入门 一,Packet Tracer介绍 packet tracer 是由Cisco公司发布的一个辅助学习工具,为学习思科网络课程的初学者去设计.配置.排除网络故障提供了网络 ...

  2. 【原创】Linux opensource-src-4.3.2.tar.gz的安装。

    下载好opensource-src-4.3.2.tar.gz 安装G++等必备库: sudo apt-get install make gcc g++ sudo apt-get install bui ...

  3. 【收集整理】Linux下的目录讲解

    Linux下的目录介绍:在Linux系统中,一切东西都是存放在一个唯一的“虚拟文件系统”中的,这个“虚拟文件系统”是树状的结构以一个根目录开始.以文件来表示所有逻辑实体和非逻辑实体,逻辑实体指文件和目 ...

  4. php date('Y')

    date('Y')默认是y-12-01 date('Y-01')!!!才是我需要的

  5. hdu 1800 Flying to the Mars

    Flying to the Mars 题意:找出题给的最少的递增序列(严格递增)的个数,其中序列中每个数字不多于30位:序列长度不长于3000: input: 4 (n) 10 20 30 04 ou ...

  6. 工作流(worfflow)

    -- 工作流(Workflow)就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务 ...

  7. Swift开发之 ---- Swift宏定义

    swift中没有了#Define这种宏定义了,可以用let来声明常量来取代,判断当前系统版本 let IS_IOS7 = (UIDevice.currentDevice().systemVersion ...

  8. C#中通过调用Dll函数时,执行一段时间后,就会报内存可能被破坏的错的解决办法

    遇到同样的问题,已经解决的:http://blog.csdn.net/youxiazzz12/article/details/24313347

  9. Java精确计算

    Java精确计算 如果我们编译运行下面这个程序会看到什么? public class Test{ public static void main(String args[]){ System.out. ...

  10. 时序图(Sequence Diagram)

    控制焦点Focus on Control 的取值: Alternative fragment(denoted “alt”) 与 if…then…else对应 Option fragment (deno ...