观察者模式:
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们自动更新自己。
现实联想:
这个模式就好像小偷偷东西,有一个或者多个人放哨(通知者),当警察来的时候,放哨的人就会通知偷东西的人(观察者)赶紧跑。
观察者模式特点
观察者模式其实就是降低耦合作用,让耦合双方都依赖于抽象而不是依赖于具体。从而使得各自代码的变化都不会影响另一边的变化。
总结:
观察者模式通过通知者检测某一事务的变化,然后当被检测事务发生变化的时候,通知者通知观察者,观察者根据被检测事务的变化也随之变化。
观察者模式实例
第一步建立通知者抽象类
abstract class Subject
{
public 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();
}
}
第二步建立通知者实体类
class ConcreteSubject : Subject
{
private string subjectState;//要通知的东西
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
第三步建立观察者抽象类
abstract class Observer
{
public abstract void Update();
}
第四步建立观察者实体类
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; }
}
}
第五步客户端代码
class Program
{
static void Main(string[] args)
{
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s, "x"));
s.Attach(new ConcreteObserver(s, "y"));
s.Attach(new ConcreteObserver(s,"z"));
s.SubjectState = "ABC";
s.Notify();
Console.ReadKey();
}
}
观察者模式的不足
在我们所使用的软件中,有些较为复杂的软件,当随着主体对象的变化而变化的事务都是封装好的这就不是观察者模式所能解决的的了
比如当主体对象发生变化的时候,观察者都封装在不同的房间(封装),如观察者一在A房间,观察者二在B房间,观察者三在C房间,这样他们就不能像观察者模式中那样在一个房间内工作,当一个通知到的时候,他们将会都知道通知的内容。这样无法满足通知所有观察者的要求。这个时候我们就要应用到事件委托
建立委托事件
Delegate void EventHandler();
第一步 :书写通知者代码
interface Subject //主体代码接口
{
void Notify();
string SubjectState//主体状态
{
get;
set;
}
}
delegate void EventHandler();
class Boss :Subject//主体的实例类
{
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
第二步写观察者代码,
因为主体通知后,因为有的观察者是单独封装的,所有的观察者不一定都能继承Observer,所以Oberver父类就没有存在的必要,因此只需要写具体的观察者类就行了
class Stockobserver
{
private string name;//观察者姓名
private Subject sub;//用来存储主体的状态
public Stockobserver (string name,Subject sub )
{
this.name = name;
this.sub = sub;
}
public void ColseStockMarket()
{
Console.WriteLine("{0}{1}关闭股市行情,继续工作!", sub.SubjectState , name);
}
}
class NBAObeserver
{
private string name;
private Subject sub;
public NBAObeserver (string name,Subject sub )
{
this.name = name;
this.sub = sub;
}
public void CloseNBAdirectSeeding()
{
Console.WriteLine("{0}{1}关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}
客户端代码
static void Main(string[] args)
{
Boss huhansan = new Boss();
//将观察者类实例化
Stockobserver tongshi1 = new Stockobserver("小明", huhansan);
NBAObeserver tongshi2 = new NBAObeserver("小刚", huhansan);
//建立一个新的委托,将这个委托托付给update这个委托类型的事件
//将tongshi1.ColseStockMarket事件委托给huhansan.Update这个事件
huhansan.Update += new EventHandler(tongshi1.ColseStockMarket);
huhansan.Update += new EventHandler(tongshi2.CloseNBAdirectSeeding);
//委托事件就好像是一个集合,可以存储多个委托
huhansan.SubjectState = "我回来了";
huhansan.Notify();
}