【C#】大话设计模式- 14 观察者模式
迪丽瓦拉
2025-05-29 00:29:39
0

观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

基本代码: 观察者模式

Subject类:可翻译为主题或者抽象通知者。一般用一个抽象类或者一个接口实现。它把所有观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

Observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个Update()方法,这个方法叫做更新方法。

ConcreteSubject类: 叫做具体主题或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

ConcreteObserver类: 具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。

using System;
using System.Collections.Generic;
using System.Text;namespace 观察者模式
{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.Read();}}//抽象主题abstract class Subject{private IList observers = new List();//观察者列表//增加观察者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; }}}}

 老板回来了,我不知道--观察者模式

using System;
using System.Collections.Generic;
using System.Text;namespace 观察者模式
{class Program{static void Main(string[] args){//老板胡汉三Boss huhansan = new Boss();//看股票的同事StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);//看NBA的同事NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);huhansan.Attach(tongshi1);huhansan.Attach(tongshi2);huhansan.Detach(tongshi1);//老板回来huhansan.SubjectState = "我胡汉三回来了!";//发出通知huhansan.Notify();Console.Read();}}//通知者接口interface Subject  //主题/通知者 接口{void Attach(Observer observer);void Detach(Observer observer);void Notify();string SubjectState{get;set;}}//秘书:具体主题或者具体通知者class Secretary : Subject{//同事列表private IList observers = new List();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 Boss : Subject{//同事列表private IList observers = new List();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);}}//看NBA的同事class NBAObserver : Observer{public NBAObserver(string name, Subject sub): base(name, sub){}public override void Update(){Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);}}
}

 

观察者模式的特点:

将一个系统分割成一系列相互协作的类有一个很好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以由任意数目的依赖它的Observer,一旦Subject的状态发生改变,所有的Observer都可以得到通知。Subject发出通知时并不需要知道谁是它的观察者,也就是说具体观察者是谁,它根本不需知道。而任何一个具体观察者不知道也不需要知道其他观察者的存在。

什么时候考虑观察者模式呢?

当一个对象的改变需要同时改变其他对象的时候。而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。

观察者模式所做的工作其实就是在接触耦合,让耦合的双方都依赖于抽象。而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。

现实编程中,具体的观察者完全有可能是风牛马不相及的类,但它们都需要根据通知者的通知来做出Update()的操。

观察者模式的不足:

尽管当点击“运行”按钮时,确实是在通知相关的控件产生变化,但它们是不可能用接口的方式来实现观察者模式的。

抽象通知者 还是依赖于 抽象观察者,万一没有了抽象观察者这样的接口,我这通知的功能就玩不成了。
事件委托实现:

using System;
using System.Collections.Generic;
using System.Text;namespace 观察者模式
{class Program{static void Main(string[] args){//老板胡汉三Boss huhansan = new Boss();//看股票的同事StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);//看NBA的同事NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);huhansan.Update += new EventHandler(tongshi1.CloseStockMarket);huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);//老板回来huhansan.SubjectState = "我胡汉三回来了!";//发出通知huhansan.Notify();Console.Read();}}//通知者接口interface Subject{void Notify();string SubjectState{get;set;}}//事件处理程序的委托delegate void EventHandler();//秘书:  具体的主题或者通知者class Secretary : Subject{//声明一事件Update,类型为委托EventHandlerpublic event EventHandler Update;//秘书的更新事件private string action;//通知方法: 触发Update事件public void Notify(){Update();}public string SubjectState{get { return action; }set { action = value; }}}//老板: 具体的主题或者通知者class Boss : Subject{//声明一事件Update,类型为委托EventHandlerpublic event EventHandler Update;//老板的更新事件private string action;public void Notify(){Update();}//主题状态或者通知消息public string SubjectState{get { return action; }set { action = value; }}}//看股票的同事class StockObserver{private string name;private Subject sub;//订阅的主题public StockObserver(string name, Subject sub){this.name = name;this.sub = sub;}//关闭股票行情public void CloseStockMarket(){Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name);}}//看NBA的同事class NBAObserver{private string name;private Subject sub;//订阅的主题public NBAObserver(string name, Subject sub){this.name = name;this.sub = sub;}//关闭NBA直播public void CloseNBADirectSeeding(){Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);}}
}

 事件委托说明:

委托就是一种引用方法的类型。一旦委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。。委托可以看做是对函数的抽象,是函数的“类”。委托的实例将代表一个具体的函数。

new EventHandler(tongshi1.CloseStockMarket) 其实就是一个委托的实例。而它就等于将 “tongshi1.CloseStockMarket”这个方法委托给“huhansan.Update”这个方法了。

一个委托可以搭载多个方法,所有方法被依次唤起。

可以使得委托所搭载的方法并不需要属于同一个类。

委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。

先有观察者模式,再有委托事件技术的。它们各有优缺点,可以看看MSDN。

相关内容