为什么要用这个模式?
1、建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。
2、一个通知者可以对应多个观察者,并且他们之间没有相互联系。
3、观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
是什么?
定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新
观察者模式包含以下四种角色:
1、Subject:目标
2、ConcreteSubject:具体目标
3、Observer:观察者
4、ConcreteObserver:具体观察者
UML图:
解说:Subject是抽象类,而具体的通知者需要继承这个抽象类。Observer是一个接口,具体的观察者需要去实现这个接口。而两个具体的子类通过图中的两句代码产生了一定的联系
举例:一个公司里同事有看股票的涨幅,有看NBA的,这个时候需要前台秘书来通知,也可能秘书没有时间通知,直接被老板撞见,所以这个时候老板和秘书都是通知者,而同事是观察者。
代码如下:
客户端代码:
static void Main(string[] args)
{
Boss huhansan = new Boss();
//看股票的同事
StockObserver tongshi1 = new StockObserver("啦啦", huhansan);
StockObserver tongshi2 = new StockObserver("笑话", huhansan);
huhansan.Attach(tongshi1);
huhansan.Attach(tongshi2);
huhansan.Detach(tongshi1);
//老板回来
huhansan.SubjectState = "我胡汉三回来了";
//发出通知
huhansan.Notify();
Console.ReadKey();
}
通知者接口
interface Subject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState
{
get;
set;
}
}
具体的通知类
老板
class Boss: 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 Secretary: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 StockObserver:Observer
{
public StockObserver(string name,Subject sub):base(name,sub)
{
}
public override void Update()
{
Console.WriteLine("{0}{1}关闭股票行情,继续工作!",sub.SubjectState, name);
}
}
}
以上摘出来的那些是通过他们让子类之间产生了关联
实例2:
假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫。
观察者模式的优点:
1、实现表示层和数据逻辑层的分离
2、抽象了更新接口,可以有各种各样不同的表示层作为具体观察者角色
3、在观察目标和观察者之间建立一个抽象的耦合
4、符合“开闭原则”的要求
缺点:
1、如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能导致系统崩溃
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的。
扩展:
其实这种模式可以扩展出委托,那么委托具体是个什么东西呢?现在我们只需要知道它可以传递方法的一个类就可以了!