“猫叫、老鼠跑、主人醒”是一个很古老的话题了,大家也都有各自的想法和解决方案。我也是看了很多,一开始的时候是相当的迷糊,这个怎么就是面试题了?考的是啥呀,和编程有关系吗?又是猫又是老鼠的,晕死了。后来遇到有人写就去凑凑热闹看几眼。但还是迷迷糊糊。后来学习了面向对象的知识,知道了接口、委托,然后又看了《大话设计模式》。

这时候再回过头去看猫呀、老鼠什么的,才能看懂一点。为什么只是看懂一点呢?因为还是不知道这个东东和写代码有啥关系,呵呵。再再后来,在自己写代码的时候,为了解决问题而用了使用了接口;为了提高运行效率而采用js+ajax时,要解决“主页面”和子页面(iframe里的页面)的事件调用的问题。都解决了之后,才对观察者模式有了更深入的理解。再去看相关的文章才能看得懂。(好像我把顺序给弄反了呀)

webform的时候,感觉观察者模式比较鸡肋,因为web是无状态的,客户端可以主动访问服务器端,但是服务器端却不能主动找到客户端。这个……太烦人了。webform是怎么解决的呢?每次访问的时候都重新注册一遍。这个效率呀,虽然好像影响不大,但是知道原理之后就是感觉不爽。

学习js快一年了,越学习越是感觉js的强大,同时也感觉,如果用javascript来实现“猫叫、老鼠跑、主人醒”的话,是不是更易读一些呢?看C#代码的时候,轻则接口、重则委托,如果这些我都不熟悉那么我咋看?当然你可以怪我基础知识不扎实,呵呵。但是我想js能够更明确的表达出来观察者模式的意图吧。

我的理解和大家的好像不大一样,猫叫,声音传递了出去,老鼠听到了开始跑,跑动的声音发出去了,主人被吵醒。那么谁是观察者呢?传递声音的介质 —— 空气!空气在观察哪里发出了声音,然后把声音传递出去,传递给订阅者。这个是很自然而然的事情吧,没有任何的牵强。

如果说老鼠是观察者,他在主动观察猫是不是发出了声音,听到了就跑,这个还勉强说得过去。但是主人呢?按照这个逻辑来说,主人也是观察者,他在主动观察老鼠跑动的声音,听到了就会醒。这个就说不过去了。人在睡觉的时候还会去主动观察声音吗?士兵在执行任务的时候会这么做,但是睡不好觉的。为了睡个好觉是不会去主动观察的。那么为什么会被吵醒呢?不是说好了,是“吵”醒嘛,是被动接收的,就是说他是订阅者,订阅了消息。有消息告诉我,而不是主动观察消息。同理老鼠也是一样。

好了言归正传,开始说代码实现

因为是js的,所以需要先介绍一下页面结构,因为老鼠、猫、主人都是独立个体,可以不放在一个页面里,所以我就设置了一个页面,里面放了三个iframe,分别指向 老鼠页、猫页、主人页。另一个原因就是,我们在做后台管理的时候,一般也是先弄一个页作为主页,然后在里面放个树,在放个tab标签,然后动态开n个iframe,每个iframe都是一个简单的功能页面。这样就和实际情况比较接近了。

先定义传播声音的介质 —— 空气

//定义传播声音的介质 —— 空气

var air = function() {var events ={

SubjectEvent: []//订阅者的注册事件,当有情况时触发这些事件

};//添加订阅者的接收消息的事件。

this.addSubjectEvent = function(e) {

events.SubjectEvent.push(e);

writeLog("[观察者接收了一个注册事件,接收事件数量:" + events.SubjectEvent.length + "。]
");

};//监听声音。理论上是去监听,但是这里还是得被动调用。

this.sendSound = function(info) {

writeLog("[观察者开始传递声音,接收事件数量:" + events.SubjectEvent.length + "。]
");

Notify(info);

}//发出通知。

var Notify = function(info) {//有发出声音的时候通知订阅者,就是遍历他们注册的事件

for (var i = 0; i < events.SubjectEvent.length; i++) {var sound = "";if (typeof info.Sound != "undefined") {

sound=info.Sound;

}

writeLog("  [观察者发出了一个通知 —— " + sound + "]
");

events.SubjectEvent[i](info);

}

}

}

然后分别是猫、老鼠、和主人

var cat = function(name) {var name =name;this.sendSound;//猫叫

this.cry = function() {//发出声音

parent.writeLog("
" + name + "开始喵喵叫。
");if (typeof this.sendSound != "undefined") {//触发事件

parent.writeLog("声音传递了出去。
");this.sendSound({ Sound: "喵喵叫", Volume: 3});

}

}

parent.writeLog("我是" + name + ",有人按俺就叫。
");

}

老鼠

//可以看做是定义了一个类,当然并不准确

var mouse = function(name) {var name = name; //可以看做是私有成员

this.sendSound; //可以看做是公有成员

var _self = this;//事件——老鼠跑

this.run = function(info) {

parent.writeLog(name+ "听到了声音。
");if (typeof info.Sound != "undefined") {//有声音,判断

if (info.Sound == "逛逛跑") {//自己跑步的声音,不处理了,要不就死循环。

parent.writeLog(name + "听到了自己的跑步声音。
");

}else{//其他声音,跑吧,不判断了。

parent.writeLog(name + "开始狂飙。
");//发出声音

if (typeof _self.sendSound != "undefined") {

parent.writeLog(name+ "狂飙发出了声音。
");

_self.sendSound({ Sound:"逛逛跑", Volume: 7});

}

}

};

}

parent.writeLog("我是" + name + ",出来找吃的。
");

}

主人

var person = function(name) {var name =name;var isWark = false;this.sendSound;//主人听到声音

this.hearSound = function(info) {if(isWark) {

parent.writeLog(name+ "已经醒了。
");

}else{if (typeof info.Volume != "undefined") {if (info.Volume <= 5) {

parent.writeLog("声音小," + name + "继续睡觉。
");

}else if (info.Volume > 5) {

parent.writeLog("声音大," + name + "被吵醒。
");

isWark= true;

}

}

}

};

parent.writeLog("我是" + name + ",俺睡着了。
");

};

然后是实例化和调用

var myAir = newair();//显示消息

functionwriteLog(msg) {

document.getElementById("msg").innerHTML +=msg;

};

var Tom = new cat("小猫咪汤姆");

window.οnlοad= function() {

Tom.sendSound= parent.myAir.sendSound; //发出声音的事件

};

var Jerry = new mouse("小老鼠杰瑞");var longtao = new mouse("可怜的龙套甲");

window.οnlοad= function() {

Jerry.sendSound= parent.myAir.sendSound; //发出声音的事件

longtao.sendSound = parent.myAir.sendSound; //发出声音的事件

//杰瑞很聪明,注意听声音,申请了一个订阅 —— 有声音俺就 run

parent.myAir.addSubjectEvent(Jerry.run);//为了做对比,龙套甲就不能去申请了。

};

var Master = new person("主人");

window.οnlοad= function() {//主人睡觉了,但是为了发生意外,还是申请一个订阅吧,要不然万一着火了我还呼呼呢。

parent.myAir.addSubjectEvent(Master.hearSound);

};

javascript里没有接口和委托的概念,但是并不是说没有这些功能,而是说不用去定义,直接用就可以。

比如 myAir.addSubjectEvent(),可以直接把一个“事件”(Master.hearSound)当作参数传递进去,非常方便。

最后是开始表演

点俺俺就喵喵叫

在线演示 (需要点一下第二个iframe里的“点俺俺就喵喵叫”,才会开始运行)

ps:快速理解javascript 的一种方法。这个方法不准确,只是用于熟悉c#、但是不熟悉js的人可以快速入门用。

Java猫叫的方式,以【猫叫、老鼠跑、主人醒】为例子,使用 javascript 来实现 观察者模式 (有在线演示)...相关推荐

  1. 一道事件委托面试题 - 猫叫老鼠跑主人醒

    /* 道事件委托面试题 - 猫叫老鼠跑主人醒 */using System;namespace CatCry {class MainClass{static void Main(string[] ar ...

  2. Java猫叫老鼠跑人惊醒_面试题:猫叫、老鼠跑、人醒的一点看法

    这些天一直在面试中,做着不同的面试题,唉,悲催 上周做的一道面试题今天正好出现在园里的首页,看了一下这位同学的实现,基本上方向是对的,就是代码上细节没有注意,有一些错误,这里我就写一下我的理解 --- ...

  3. python狗图像识别_使用pytorch完成kaggle猫狗图像识别方式

    kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据库.编写和分享代码的平台,在这上面有非常多的好项目.好资源可供机器学习.深度学习爱好者学习之用. 碰巧最近入门了一门非常的深度学习框 ...

  4. Java猫叫老鼠跑人惊醒_关于猫叫、老鼠逃跑、人被惊醒的程序设计

    题目是这样的:猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒. 要求: 1.要有联动性,老鼠和人的行为是被动的 2.考虑可扩展行,猫叫声可能会引起其他联动效应 看到这个程序设计题目,我的第一反应是用事件 ...

  5. Java猫叫老鼠跑人惊醒_用代码表示如下情景:猫叫、老鼠逃跑、主人惊醒

    ### 1. 定义猫类型,并且该类型负责维护猫叫事件 *Cat.cs* ```csharp using System; namespace CatCry { /// /// 猫类型,维护猫叫事件 // ...

  6. 让猫给人打工,猫咖是一门好生意吗?

    「核心提示」 大眼圆脸.酷似人类幼崽的猫咪成为空巢青年的新宠.瞄准了爱猫却没条件养猫的人,猫咖生意兴起.开一家猫咖店赚钱吗?实际是并不如想象中美好.接客的"猫主子"既是这个生意的亮 ...

  7. 猫和老鼠玩象棋,玩了M+N局,猫赢了M局 老鼠赢了N局 NM,而且在整个过程中,猫的得分从来没有超过过老鼠,问共有多少种可能的比赛得分过程

    1. 猫和老鼠玩象棋,玩了M+N局,猫赢了M局 老鼠赢了N局 N>M,而且在整个过程中,猫的得分从来没有超过过老鼠,问共有多少种可能的比赛得分过程 2. 每日早上淘宝网办公楼对面的烧饼店都有人排 ...

  8. python编程猫下载_【编程猫软件下载】编程猫客户端 V1.6.5 电脑版-开心电玩

    软件介绍 编程猫软件是深圳点猫科技有限公司开发的一款具有教育类性质的编程工具平台,主要针对6-16岁的少儿群体进行编程教育.通过平台自有的图形化课程,培养孩子们的逻辑思维能力与创造力,让他们在平台上创 ...

  9. 以太网的光猫和光纤的光猫有什么区别吗?

    光调制解调器,光猫也称为单端口光端机,是针对特殊用户环境而研发的一种三件一套的光纤传输设备.该设备采用大规模集成芯片,电路简单,功耗低,可靠性高,具有完整的告警状态指示和完善的网管功能.光猫可以分为以 ...

  10. Java 多线程的基本方式

    Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

最新文章

  1. phpstudy本地调试运行TP5的后台源码
  2. PyQt5 简易计算器
  3. python axis=0 axis=1的区别
  4. 安徽大学计算机科学与技术复试线,安徽大学计算机考研报录比及分数线
  5. 中北大学c语言程序设计期末_中北大学:工作室联合育人 家校情温暖寒冬
  6. java动态代理技术
  7. 设计模式:依赖倒置原则
  8. java设计一百亿的计算器_请设计一个一百亿的计算器
  9. 7. PHP Xhprof
  10. zookeeper 可以干什么
  11. ConditionalDetr论文解读+核心源码解读
  12. 情人节主题的公众号图文排版怎样设计最走心?
  13. linux red hat 8.0 root密码破解
  14. 微信群发消息怎么发?微信群发消息只需要4步?
  15. Internet Download Manager 6.37.15简体中文版
  16. vue 项目下JS内存溢出
  17. Qt:Qt Widgets
  18. ​12864无字库液晶显示(一)
  19. 瓦克美国多晶硅基地爆炸 多晶硅及硅片或涨价
  20. pytdx 获取板块指数_通达信如何查看行业板块和概念板块的指数和K线图

热门文章

  1. k8s重要概念及部署k8s集群(一)
  2. Mono.Cecil简介与示例
  3. ue4/5玻璃材质制作(简单易懂上手)
  4. NUC8i7HNK下ubuntu16.04LTS安装realsense
  5. 在 Intel NUC8i7HVK 上安装CentOS7
  6. Google jib插件的使用
  7. 【生信分析】基于TCGA肿瘤数据进行基因共表达网络分析
  8. python控制多个屏幕_使用python的多个屏幕
  9. 网络历史之金融投资三剑客01
  10. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon runn