还早很早以前就看到个这个面试题,当然在书上也有类似的题目,书上是说通过委托事件来处理这个问题,而后来也知道,这个问题也可以通过设计模式中的观察者模式来处理,所以当时也没有深入去思考,今天刚巧翻到这样的题目,查看评论,发现里面的道理还不简单,这里只引用里面的几个评论:
不玩设计模式。
对于c#来说(也包括所有.net平台开发语言以及早期的vb版本都是基于事件驱动方式),就是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
using System; namespace ConsoleApplication1 { class Program { static void Main( string [] args) { 老鼠 m = new 老鼠(); 人 p = new 人(); 猫 c = new 猫(); m.跑了 += c.叫; m.跑了 += p.醒了; Console.WriteLine( "测试开始............" ); m.开跑(); Console.WriteLine( "..................测试结束!" ); Console.ReadKey(); } } public class 老鼠 { public event Action 跑了; public void 开跑() { Console.WriteLine( "老鼠跑" ); if (跑了 != null ) 跑了(); } } public class 猫 { public void 叫() { Console.WriteLine( "猫叫" ); } } public class 人 { public void 醒了() { Console.WriteLine( "人醒了" ); } } } |
这里最关键的就是让两个完全不同class的对象实例去监听老鼠跑的动作,如果写出这两句就可以100分了。
要注意:事件不需要纠缠(耦合)类型!当你设计“人”和“猫”类时,根本不依赖“老鼠”类型,这样才能体现依赖倒置的需求(在将来的工程中才设计使用事件的新类型)。
如果你在设计使用事件的类型是,还要纠缠触发事件的类型定义,那么就白学设计了(白学设计模式了),赶紧“幡然醒悟”吧!
哦补充一下:当你设计“人”和“猫”类时根本不依赖“老鼠”类型,在设计“人”和“猫”类的行为时,也不知道调用者要如何绑定行为。
你在设计“人”类是,怎么就知道只是
1
|
public Man(IRatSubject[] ratSub, ICatSubject catSub) |
这个定义呢?你封装了“人”类进类库中,然后使用它的程序员把人跟“闹钟”关联起来,“闹钟一响人就醒了”。人醒了可以有无限种可能性,但是都设计“人”类时的职责。
设计模式如果成为八股文就会让人错误地滥用起来,设计模式只有观摩意义而对于许多开发者其实是一种坏味道。