《深入浅出设计模式-中文版》读书笔记-观察者模式(四)
2010-07-06 06:34 Virus-BeautyCode 阅读(2523) 评论(1) 编辑 收藏 举报今天要接触的是观察者模式Observer。
提到观察者,肯定会想到还应该有被观察者,也就是观察的内容,或者说是观察的主题。
首先让我们看看报纸和杂志的订阅是怎么回事:
- 报社的业务就是出版报纸。
- 向一家报社订阅报纸,只要有新报纸,就会给你送过来。只要你是他们的订阅者,就一直会收到。
- 当你不想继续看报纸的时候,可以取消订阅,他们就不会再送报纸过来。
- 只要报社存在,就会一直有人订阅或者是取消订阅。
上面就是一个典型的观察者模式,你、我、他,这些订阅报纸的人就是观察者Observer,报社就是被观察者,观察的主题Subject。
观察者模式的定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态的时候,它的所有依赖者都会收到通知并自动更新。
观察者有很多的实现方式,最常见的是包含Subject与Observer接口的类设计。
上图是我从书中摘取出来的。
-
当两个对象之间松耦合,他们依然可以交互,但是不清楚彼此的细节。观察者模式提供了一种对象设计,实现主题和观察者之间的松耦合。
-
对于观察者的一切,主题只是知道观察者实现了某一个接口(也就是Observer接口)。主题不需要知道观察者具体是做什么的类。
-
任何时候我们都可以添加新的观察者,主题只是依赖于观察者列表,添加观察者也就是在列表中添加元素。同样,也可以删除观察者,也就是删除观察者列表的元素。
-
有新类型的观察者,主题不用修改代码,只要新的观察者实现Observer接口就可以了。只需要在主题中注册观察者,然后就可以收到新通知了。
-
二者是松耦合的,相互之间不影响,只要接口被遵守,就可以自由的改变他们。
设计原则:
为了交互对象之间的松耦合设计而努力。
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First.Observer
{
public interface IObserver
{
void Update();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First.Observer
{
public interface ISubject
{
IList<IObserver> Observers { get; set; }
void Register(IObserver observer);
void UnRegister(IObserver observer);
void NotifyObserver();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First.Observer
{
public class SubjectImpl:ISubject
{
public SubjectImpl()
{
_observers = new List<IObserver>(0);
}
private IList<IObserver> _observers;
public IList<IObserver> Observers
{
get { return _observers; }
set { this._observers=value ; }
}
public void Register(IObserver observer)
{
_observers.Add(observer);
}
public void UnRegister(IObserver observer)
{
_observers.Remove(observer);
}
public void NotifyObserver()
{
if (_observers != null)
{
foreach (IObserver ob in _observers)
{
ob.Update();
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First.Observer
{
public class ObserverImpl:IObserver
{
private string _name;
public ObserverImpl(string name)
{
_name = name;
}
public void Update()
{
Console.WriteLine("{0}收到通知了",_name );
}
}
}
客户端调用代码
Head.First.Observer.ISubject subject = new Head.First.Observer.SubjectImpl();
Head.First.Observer.IObserver ob1 = new Head.First.Observer.ObserverImpl("ob1");
Head.First.Observer.IObserver ob2 = new Head.First.Observer.ObserverImpl("ob2");
Head.First.Observer.IObserver ob3 = new Head.First.Observer.ObserverImpl("ob3");
subject.Register(ob1);
subject.Register(ob2);
subject.Register(ob3);
subject.NotifyObserver();
从上面的代码结构中可以看出来如果需要增加一个新的观察者,只需要新观察者实现IObserver接口,然后再主题中register就可以了。
但是上面的观察者模式也还是有一点强依赖的意味,就是主题类依赖于观察者列表,有新的观察者就需要主题类主动注册。又没有可能主题也不关心有没有什么新观察者,只是专注于属于自己的职责-通知主题的内容变化。
其实在.NET中有一种天然存在的设计模式,就是观察者。大家都知道.NET是事件驱动的形式,就是控件的事件引发方法的调用,让触发事件的一方得到信息。我们可以将这个原理引入观察者模式的实现上来。
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp
{
public delegate void ObserverEventHandler(object sender, EventObjectArgs e);
/// <summary>
/// 被观察者
/// </summary>
public interface IEventObserable
{
event ObserverEventHandler ObserverEvent;
void OnObserverEvent(EventObjectArgs e);
void RaiseObserverMethod();
}
/// <summary>
/// 观察者
/// </summary>
public interface IEventObserver
{
}
public class EventObjectArgs : EventArgs
{
private string _message;
public string Message
{
get { return _message; }
}
public EventObjectArgs()
{
}
public EventObjectArgs(string message)
{
this._message = message;
}
}
class EventCat : IEventObserable
{
#region IEventObserable 成员
public event ObserverEventHandler ObserverEvent;
public void OnObserverEvent(EventObjectArgs e)
{
if (null != ObserverEvent)
{
ObserverEvent(this, e);
}
}
public void RaiseObserverMethod()
{
Console.WriteLine("猫叫了");
OnObserverEvent(new EventObjectArgs("猫叫了"));
}
#endregion
}
class EventMouse : IEventObserver
{
public EventMouse() { }
public EventMouse(IEventObserable observable)
{
observable.ObserverEvent += new ObserverEventHandler(observable_ObserverEvent);
}
public void observable_ObserverEvent(object sender, EventObjectArgs e)
{
Console.WriteLine(string.Format("{0},所有老鼠被吓跑了", e.Message));
}
}
class EventDog : IEventObserver
{
public EventDog(IEventObserable observable)
{
observable.ObserverEvent += new ObserverEventHandler(observable_ObserverEvent);
}
public void observable_ObserverEvent(object sender, EventObjectArgs e)
{
Console.WriteLine(string.Format("{0},所有老鼠被吓跑了,但是狗拿耗子多管闲事", e.Message));
}
}
class EventMaster : IEventObserver
{
public EventMaster(IEventObserable observable)
{
observable.ObserverEvent += new ObserverEventHandler(observable_ObserverEvent);
}
public void observable_ObserverEvent(object sender, EventObjectArgs e)
{
Console.WriteLine(string.Format("{0},所有老鼠被吓跑了,但是狗拿耗子多管闲事,主人生气了,要打死这些动物", e.Message));
}
}
}
OO原则:
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
为交互对象之间的松耦合设计而努力
OO模式
观察者模式-在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。