学到观察者模式的时候,脑子里不禁回忆起了高中时光中的这样一段故事
时间2010年6月XX日 地点:XX中学 人物:小涛,小凡,我
那是一个风和日丽的下午,知了在树梢不停地叫,仿佛是一首催眠曲。语文老师也是在讲台上不知疲倦的讲解着著名诗歌《蜀道难》“
噫吁嚱!,危呼高哉!
蜀道之难难于上青天。
蚕丛及鱼凫,开国何茫然。。。
”
慵懒的阳光倾洒下来,微风轻抚,不知不觉间给人带来了一丝丝倦意。
只见小凡的脑袋如小鸡啄米般,一点一点。突然他抬起头,眯着眼好像下了很大决心似的
“我顶不住了,帮我看着老师,我睡会觉!”然后便埋头呼呼大睡。
另外一个小伙伴小涛,貌似精力很旺盛,正在左顾右盼,不知道寻找着什么。突然从前方伸出一只手,递给了他一本书,看其封面赫然写着《最小说》。惊喜的他面目一转,冲我嘿嘿一笑便兴致勃勃的看了起来。
从他的眼神中我看到了“帮我看着老师,我看会杂志。”
时间滴答滴答的不停走过。。。
敏锐的我突然发现 教师后门处惊现一庞大人影。机智的我迅速撞了撞小凡和小涛。不过还是晚了一步,班主任气势冲冲的走到了小凡跟前:“坐累了吧,站起来歇会!”然后转身就走了。小涛在旁边幸灾乐祸的说:“太幸运了,竟然没发现我,哈哈哈~”
语文老师还在继续“蜀道之难难于上青天。。”
只听小凡嘟囔了句“蜀道难,睡觉更难!”
真是怀念那段美好的时光~
好了废话不说了,来说说这个观察模式吧。
观察者模式:【定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得得到通知并被自动更新。】
此模式的参与者分为两大类,一类是被观察的目标(主题),另一类是观察该目标的观察者们。正因为该模式是基于“一对多”的关系,所以它一般应用于由一个目标对象和N个观察者对象组成的场合。当目标对象的状态发生改变或做出某种行为时,正在观察该目标对象的观察者们将自动、连锁地作出相应的响应。
拿上面的那个故事来分析,我和班主任充当的是ConcreteSubject 角色,小凡和小涛充当的是ConcreteObserver 角色。
代码实例:
//通知者接口
interface Subject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState
{
get;
set;
}
}
// 具体通知者 同学
class Classmate : Subject
{
//同学列表
private IList<Observer> observers = new List<Observer>();
private string action;
//增加
public void Attach(Observer observer)
{
observers.Add(observer);
}
//减少
public void Detach(Observer observer)
{
observers.Remove(observer);
}
//通知
public void Notify()
{
foreach (Observer o in observers)
o.Update();
}
//同学状态
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
// 可怕的通知者 班主任
class Headteacher : Subject
{
//同学列表
private IList<Observer> observers = new List<Observer>();
private string action;
//增加
public void Attach(Observer observer)
{
observers.Add(observer);
}
//减少
public void Detach(Observer observer)
{
observers.Remove(observer);
}
//通知
public void Notify()
{
foreach (Observer o in observers)
o.Update();
}
//班主任状态
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
//抽象观察者
abstract class Observer
{
protected string name;
protected Subject sub;
public Observer(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}
//具体观察者, 睡觉的同学
class SleepStudent : Observer
{
public SleepStudent(string name, Subject sub)
: base(name, sub)
{
}
public override void Update()
{
Console.WriteLine("{0} {1} “坐累了吧,站起来歇会!”", sub.SubjectState, name);
}
}
//看杂志的同学
class MagazineObserver : Observer
{
public MagazineObserver(string name, Subject sub)
: base(name, sub)
{
}
public override void Update()
{
Console.WriteLine("{0} {1} 没收杂志,好好听课!", sub.SubjectState, name);
}
}
客户端代码:
static void Main(string[] args)
{
//班主任
Headteacher laowang = new Headteacher();
//睡觉的小凡
SleepStudent xiaofan = new SleepStudent("小凡", laowang);
//看杂志的小涛
MagazineObserver xiaotao = new MagazineObserver("小涛", laowang);
laowang.Attach(xiaofan);
laowang.Attach(xiaotao);
// 小涛幸运的没被班主任发现,逃过一劫!
laowang.Detach(xiaotao);
//班主任偷偷来
laowang.SubjectState = "班主任气势冲冲的来到了小凡面前:\n \n";
//发出通知
laowang.Notify();
Console.WriteLine("\n PS:小涛幸运的没被班主任发现,逃过一劫! ");
Console.Read();
}
效果:
额,在班主任不按套路出牌的时候,我的作用仿佛也不是很大。。
小结:
观察者模式还可以用我们常用的“博客订阅”来解释。某某同学的博客被其他很多同学所订阅,每当他更新博客的时候,所有订阅他博客的同学都可以得到通知。(某某同学即为主题Subject,订阅他博客的同学为观察者Observer) 然而某某同学更新博客发通知的时候,并不知道谁订阅了他的博客,订阅某某博客的同学也不知道其他的订阅者。 这两个“不知道”正是体现了依赖倒转原则。
总之观察模式所做的工作就是在解除耦合,让耦合的双方都依赖于抽象,而不是具体。