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是我比较熟悉的设计模式之一,在平常的开发过程中,也曾几次用到,它主要适用于如下场景: ...
随机推荐
- Python3 字符编码
编码 字符串是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节 ...
- C# 制作卸载文件
1.建一个控制台应用程序Uninstall: 2.在应用程序的mian方法中添加 static void Main(string[] args) { System.Diagnostics.Proces ...
- Config IIS server6.0-- HTTP 错误 500.21 - Internal Server Error 解决方案
HTTP 错误 500.21 - Internal Server Error 解决方案 不久前重新安装了Windows7,在安装了VS2010 开发平台之后,将网站发布到IIS,访问发 ...
- 要将表的限制条件写到与该表同级别的where中
测试目的:将朱查询的限制条件放到子查询的where中,查看性能影响. 测试数据:create table t1 as select object_id,object_name from dba_obj ...
- 欧几里得旅行商问题 java与c++实现
双调欧几里得旅行商问题是一个经典动态规划问题.<算法导论(第二版)>思考题15-1 旅行商问题描述:平面上n个点,确定一条连接各点的最短闭合旅程.这个解的一般形式为NP的(在多项式时间内可 ...
- Log4j与common-logging
Log4j与common-logging 总网上搜了些Log4j与common-logging的介绍,记录下. 一.Log4j 1.简介 Log4j是Apache的一个开放源代码项目 使用Log4j ...
- [Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】
题目链接:CF Round #254 div1 C 题目分析 这道题目是要实现区间赋值的操作,同时还要根据区间中原先的值修改区间上的属性权值. 如果直接使用普通的线段树区间赋值的方法,当一个节点表示的 ...
- POJ 2886 Who Gets the Most Candies?(反素数+线段树)
点我看题目 题意 :n个小盆友从1到n编号按顺时针编号,然后从第k个开始出圈,他出去之后如果他手里的牌是x,如果x是正数,那下一个出圈的左手第x个,如果x是负数,那出圈的是右手第-x个,游戏中第p个离 ...
- UITableView.m:8042 crash 崩溃
CRASH : /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.6.21/UITableView.m:804 ...
- Perl脚本学习经验(四)--Perl中sftp的使用
使用sftp,需要使用Except模块,该模块需要下载安装在perl目录下,可以上http://www.cpan.org/上下载对应的安装包:1. 用root用户登录环境:2. cd /usr/lib ...