这个是 昨天 练习 事件代理 的时候想到 的.
于是今天就 试一把
由于昨天 写的 那个程序
基本功能: 在 Cat 类对象 Shout() 之后 订阅 事件 的 所有 Mouse 类对象都 会 执行 Run() 方法;.
但是 在每次 有 新的 事件订阅者的时候 必须 添加 一行
tomcat.CatShoutEvent +=new CatShoutEventHandler(jacky.run);
这一点我想 设计成 只要 声明了的mouse类对象 ,都会自动执行 响应函数;
ok! 开始了
存在问题:
1. 如何在 对象 创建时 便让 其他类 知道
2. 如何 全局 获取 并通知 所有 对象执行相应的方法
解决方法 : 用单例模式的思想 来获得 一个 对象 而且 该 使用 该对象 保存所有 Mouse 类的 对象的 引用 ,
同时应用 Observer 模式 , 通知所有 类对象 来执行 相应的方法..
文件结构
│ AbstractCat.cs ---------Cat 的 抽象类
│ AbstractMouse.cs----------Mouse 的 抽象类
│ Cat.cs ----------Cat 类
│ ITalk.cs ----------Talk能力接口
│ Mouse.cs ----------Mouse
│ Program.cs ---------主函数 所在类
│ ShoutEventArgs.cs---------时间参数类 继承自 EventArgs
│ SuperCat.cs ----------超级猫 类
│ SuperMouse.cs -----------超级 老鼠 类
├─MouseFactory 工厂方法所在包: 生产 老鼠
│ IFactory.cs -------工厂接口
│ mouseFactory.cs -------生产 Mouse
│ superMouseFactory.cs --------生产超级老鼠
│
├─Observer ---------Observer模式 所在包:
│ IObserver.cs ---------Observer接口
│ Observable.cs ----------- 事件通知者类: 其间 包含 所有 Mouse对象 的 引用 ,还有 通知 所有Mouse 对象 执行 对 猫的shout() 之后的 Action 方法
将 Observer 声明为 接口 使得 所有的 实现了 该接口的 类 都可以 被通知
IObserver.cs:
2 {
3 void Action(object sender,ShoutEventArgs e);
4 }
Observable.cs :
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace delegateTry.Observer
7 {
8 class Observable
9 {
10 private IList<IObserver> mouses;
11
12 private static Observable observable;
13
14 private static readonly object syncForLock = new object();
15
16 private Observable()
17 {
18 mouses = new List<IObserver>();
19 }
20
21 //单线程情况
22 public static Observable GetInstance()
23 {
24 if (observable == null)
25 {
26 observable = new Observable();
27
28 return observable;
29 }
30
31 else
32 {
33 return observable;
34 }
35 }
36
37 //多线程
38 /*
39 * 在本程序中没用上
40 */
41
42 public static Observable GetInstanceForSecurity()
43 {
44 if (observable == null)
45 {
46 lock (syncForLock)
47 {
48 if (observable == null)
49 {
50 observable = new Observable();
51 }
52 }
53
54 return observable;
55 }
56
57 else
58 {
59 return observable;
60 }
61 }
62
63 //添加 订阅者 或者说 观察者
64 public void AddObserver(IObserver amouse)
65 {
66 this.mouses.Add(amouse);
67 }
68
69 //删除 订阅者 或者说 观察者 对象
70 public void DelObserver(IObserver amouse)
71 {
72 this.mouses.Remove(amouse);
73 }
74
75
76 // 观察者 的反应
77 public void Action(object sender ,ShoutEventArgs e)
78 {
79 foreach (IObserver item in this.mouses)
80 {
81 item.Action(sender,e);
82 }
83 }
84
85 }
86 }
87
上面 使用单例 来 使得 所有 实现了 Iobserver 对象 的 引用 都可以 被 存放在 同一 个 对象中.; 并且 在 事件 被触发时 都被通知到
如何 保证 Mouse 对象的 引用 都被 存放进 Observer 的同一个对象中 呢...?
这里使用 factory Method 来 生产对象 同时 做一点 无耻的 工作.
2 {
3
4 AbstractMouse concreteMouse(string name);
5
6 }
Mousefactory.cs :
2 {
3
4 public AbstractMouse concreteMouse(string name)
5 {
6 AbstractMouse am = new Mouse(name);
7
8 //将其加入到 观察者对象列表中
9 Observable.GetInstance().AddObserver(am);
10
11 return am;
12
13 }
14
15 }
用这种方法 就在 生成对象 的时候 自动 的 将 引用 传递给了 Observer 对象 保存起来; 不用操心 了.
大概就是这样 ,;
贴一下 Mouse 和 Cat 类 的代码:
因为 稍微做了一下 抽象 提取 所以 还蛮多的;
2
3 abstract class AbstractCat
4 {
5 public event CatShoutEventHandler CatShoutEvent;
6
7 protected string name;
8
9
10 public AbstractCat(string name)
11 {
12 this.name = name;
13
14 }
15
16
17 public string Name
18 {
19 get
20 {
21 return name;
22 }
23 }
24
25 public virtual void Shout()
26 {
27
28 if (this.CatShoutEvent != null)
29 {
30 this.CatShoutEvent(this, new ShoutEventArgs(this.name));
31 }
32
33 }
34 }
1 class Cat:AbstractCat
3 public Cat(string name):base(name)
4 {
5
6 }
7
8 public override void Shout()
9 {
10 Console.WriteLine(" 我只会 喵..喵..----普通猫 \n\n", this.name);
11 base.Shout();
12 }
13 }
2 {
3 public SuperCat(string name)
4 : base(name)
5 {
6
7 }
8
9 public string Talk()
10 {
11 return ("bull shit! cut your crap!\n");
12 }
13
14
15 public override void Shout()
16 {
17 Console.WriteLine("! this is {0}

18
19 Console.WriteLine(Talk());
20
21 base.Shout();
22
23 }
24
25 }
AbstractMouse 类
2 {
3 protected string name;
4
5 public AbstractMouse(string name)
6 {
7 this.name = name;
8
9 }
10
11 public virtual void run(object sender, ShoutEventArgs e)
12 {
13
14 }
15
16 public virtual void Action(object sender, ShoutEventArgs e)
17 {
18 run(sender,e);
19 }
20
21 }
2 {
3 public Mouse(string name)
4 : base(name)
5 {
6
7 }
8
9
10 public override void run(object sender,ShoutEventArgs e)
11 {
12 Console.WriteLine(" {0} 来了, 我 {1} 开溜! ",e.ShoutSource,this.name);
13 }
14
15 }
2 {
3 public SuperMouse(string name):base(name)
4 {
5
6 }
7
8 public string Talk()
9 {
10 return string.Format(" Stop !, this is {0}, Let's hava a negotiation! \n",this.name);
11 }
12
13 public override void run(object sender, ShoutEventArgs e)
14 {
15 if (sender is SuperCat)
16 {
17 Console.WriteLine("{0} :: {1} \n", e.ShoutSource, Talk());
18 }
19
20 else
21 {
22
23 Console.WriteLine(" 碰上个 傻瓜猫 今天

24
25 }
26
27 }
28
29
30 }
再看下主函数:
1 class Program
3 static void Main(string[] args)
4 {
5 AbstractCat tomcat = new Cat("Tomcat");
6 AbstractCat SuperTomcat = new SuperCat("超级猫");
7
8 IFactory mouseFac = new mouseFactory();
9 IFactory superFac = new superMouseFactory();
10
11 AbstractMouse jacky = mouseFac.concreteMouse("Tacky");
12 AbstractMouse mikky = mouseFac.concreteMouse("Mikky");
13
14
15 AbstractMouse mickeyMouse = superFac.concreteMouse("米老鼠");
16
17
18 tomcat.CatShoutEvent += new CatShoutEventHandler(Observable.GetInstance().Action);
19
20 SuperTomcat.CatShoutEvent += new CatShoutEventHandler(Observable.GetInstance().Action);
21
22
23 tomcat.Shout();
24
25
26 Console.WriteLine("Tomcat shorting ends here \n\n");
27
28
29 Console.WriteLine("SuperTomcat shorting begins here \n\n");
30
31
32 SuperTomcat.Shout();
33
34
35 Console.Read();
36
37 }
38 }
主程序中 在 Cat 对象 Shout() 之后 并未 声明 通知所有 的 Mouse 对象 ; 但是 所有的 Mouse 对象 都会对此 做出 反应;
程序 运行结果 :