观察者模式定义了一种一对多的依赖关系,让多个观察者对象同事监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己
class Program
{
static void Main(string[] args)
{
ConcreteSubject concreteSubject = new ConcreteSubject();
concreteSubject.Attach(new ConcreteObserver(concreteSubject, "奶茶店"));
concreteSubject.Attach(new ConcreteObserver(concreteSubject, "快餐店"));
concreteSubject.Attach(new ConcreteObserver(concreteSubject, "花店"));
concreteSubject.SubjectState = "顾客来了";
concreteSubject.Notify();//消息通知
Console.ReadLine();
}
}
//抽象消息通知者,一般用一一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一个容器里,每个消息通知者都可以联系任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象
abstract class Subject
{
private IList<Observer> observers = new List<Observer>();//观察者列表
//增加观察者
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();
}
}
}
//抽象观察者,是所有观察者的基类,在得到消息发布者的消息后,使用更新方法更新自己的状态
abstract class Observer
{
public abstract void Update();
}
//具体消息通知者,继承自Subject的具体类,将有关状态存入具体观察者对象;在具体消息通知者内部状态改变的时候,给所有在容器中的观察者发布消息。
class ConcreteSubject : Subject
{
private string subjectState;//消息通知者的具体消息
//具体被观察者状态
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
//具体观察者,实现抽象观察者的接口,以便本身的状态与消息通知者的状态相协调
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("{0}的新状态是{1}",name,observerState);
}
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
}
观察者模式主要解决的问题:当一个对象状态发生改变后给其他的对象通知
观察者的优点:
观察者和被观察者是抽象耦合的,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
观察者的缺点:
1、如果一个被观察者对象有很多的直接或间接的观察者的话,消耗的时间会增加很多。
2、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅是知道被观察者发生变化,会有很一些不需要改变状态的观察者被迫发生状态改变。
3、如果观察者与被观察者之间有循环依赖,会造成陷入死循环中,导致系统崩溃。
发布订阅模式需要引用到了事件与委托这个两种类型
订阅发布模式,发布者的消息发送者不会讲消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心和中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地发布它们给订阅者。
优点
1、支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象
2、发布者与订阅者耦合性降低,发布者只管发布一条消息后,订阅者只监听发布者的事件名,只要发布者的事件名不变,它不管发布者如何改变
缺点
1、创建订阅者需要消耗一定时间的内存
2、增加维护的难度
区别与联系
联系:
订阅发布是观察者模式的一种变种。
区别:
1、观察模式中观察者和被观察者是松耦合的关系、发布-订阅模式中完全不存在耦合。
2、观察模式中观察者与被观察者相互感知,发布-订阅模式中存在中间调度工厂。
class Program
{
static void Main(string[] args)
{
Client c1 = new Client();
ObserverA a = new ObserverA("路北", c1);
ObserverB b = new ObserverB("路南", c1);
c1.Update += new Handler(a.Work);
c1.Update += new Handler(b.Work);
c1.SubjectState = "顾客";
c1.Notify();
}
}
interface Subject
{
public void Notify();
string SubjectState
{
get;
set;
}
}
delegate void Handler();//声明委托
class Client : Subject
{
public event Handler Update;//声明Handler(事件处理程序)的委托事件Update方法
private string action;
public void Notify()//引发Update方法
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
class ObserverA
{
private string name;
private Subject subject;
public ObserverA(string name, Subject subject)
{
this.name = name;
this.subject = subject;
}
public void Work()
{
Console.WriteLine("{0}来了,{1}开始工作",subject.SubjectState,name);
}
}
class ObserverB
{
private string name;
private Subject subject;
public ObserverB(string name, Subject subject)
{
this.name = name;
this.subject = subject;
}
public void Work()
{
Console.WriteLine("{0}来了,{1}开始工作", subject.SubjectState, name);
}
}