观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
我们通过一个简单例子来学习观察者模式,小强和小明订阅了网易的新闻,当网易新闻更新时,网易会自动通知小明和小强告诉它们新闻已经更新。
下面就是我们的实现过程,首先来了看下类图:
接下来我们来看下代码的书写:
首先是抽象通知者接口,可以增加和移除、通知观察者对象。
//通知者接口
interface Subject
{
//增加观察者
void Attach(Observer observer);
//移除观察者
void Detach(Observer observer);
//通知观察者
void Notify();
//通知者自己状态
string SubjectState
{
get;
set;
}
}
然后是具体通知者也就是网易,将有关状态存入本身,在新闻更新时,给所有登记过的观察者发出通知。
//网易
class 网易 : 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 订阅者小明 : Observer
{
public 订阅者小明(string name, Subject sub)
: base(name, sub)
{
}
//重写“更新”方法
public override void Update()
{
Console.WriteLine("{0}{1}欢迎您查看您所订阅的网易新闻。", sub.SubjectState, name);
}
}
//订阅者小强
class 订阅者小强 : Observer
{
public 订阅者小强(string name, Subject sub)
: base(name, sub)
{
}
public override void Update()
{
Console.WriteLine("{0}{1}欢迎您查看您所订阅的网易新闻。", sub.SubjectState, name);
}
}
最后是客户端代码:
//网易
网易 wangyi = new 网易();
//订阅者小明
订阅者小明 xiaoming = new 订阅者小明("小明", wangyi);
//订阅者小强
订阅者小强 xiaoqiang = new 订阅者小强("小强", wangyi);
wangyi.Attach(xiaoming);
wangyi.Attach(xiaoqiang);
//网易新闻更新
wangyi.SubjectState = "网易:我们的新闻已经更新。 ";
//发出通知
wangyi.Notify();
最后我们运行的结果是:
以上这就是一个简单的观察者模式的小例子。
观察者模式它的使用条件时:
1.当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2.当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
3.当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
最后做下总结:
观察者模式所作的工作就是解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化不会影响另一边的变化,这样就大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。