观察者模式又叫做发布-订阅(Publish/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。[DP]
using System;
using System.Collections.Generic;
namespace 设计模式_观察者模式
{
/// <summary>
/// 抽象通知者类
/// Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现。
/// 它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。
/// 抽象主题提供一个接口,可以增加和删除观察者对象。
/// </summary>
abstract class Subject
{
private List<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 (var observer in observers)
{
observer.Update();
}
}
}
/// <summary>
/// ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体观察者对象;
/// 在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
/// 具体主题角色通常用一个具体子类实现。
/// </summary>
class ConcreteSubject :Subject
{
private string subjectState;
//具体被观察者状态
public string SubjectState { get => subjectState; set => subjectState = value; }
}
/// <summary>
/// 抽象观察者类
/// Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
/// 这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。
/// 更新接口通常包含一个Update()方法,这个方法叫做更新方法。
/// </summary>
abstract class Observer
{
protected string name;
protected ConcreteSubject subject;
public Observer (string name, ConcreteSubject subject)
{
this.name = name;
this.subject = subject;
}
public abstract void Update();
}
/// <summary>
/// 具体观察者
/// ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
/// 具体观察者角色可以保存一个指向具体主题对象的引用。
/// 具体观察者角色通常用一个具体子类实现。
/// </summary>
class ConcreteObserver1 : Observer
{
public ConcreteObserver1 (string name, ConcreteSubject subject):base(name,subject)
{
}
public override void Update()
{
Console.WriteLine("{0}, {1}不打游戏了",subject.SubjectState,name);
}
}
class ConcreteObserver2 : Observer
{
public ConcreteObserver2(string name, ConcreteSubject subject) : base(name, subject)
{
}
public override void Update()
{
Console.WriteLine("{0},{1}不摸鱼了",subject.SubjectState,name);
}
}
class Program
{
/// <summary>
/// 客户端代码
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
ConcreteSubject subject = new ConcreteSubject();
subject.Attach(new ConcreteObserver1("小林",subject));
subject.Attach(new ConcreteObserver2("小周",subject));
subject.SubjectState = "老板来了";
subject.Notify();
}
}
}
结果显示
事件委托的使用 实现观察者模式
/// <summary>
/// 事件委托的使用 实现观察者模式
///
/// “抽象通知者”由于不希望依赖“抽象观察者”,
/// 所以“增加”和“减少”的方法也就没有必要了(抽象观察者已经不存在了)。
/// </summary>
interface Subject1
{
//通知
void Notify();
string SubjectState
{
get;set;
}
}
//声明一个委托,名称叫“EventHandler(事件处理程序)”,无参数,无返回值。
delegate void EventHandler();
class Boss : Subject1
{
public event EventHandler Update;
private string action;
public string SubjectState { get => action; set => action=value; }
public void Notify()
{
Update();
}
}
/// <summary>
/// “看股票观察者”类和“看NBA观察者”类,去掉了父类“抽象观察类”,
/// 所以补上一些代码,并将“更新”方法名改为各自适合的方法名。
/// </summary>
class StockObserver
{
protected string name;
protected Subject1 subject;
public StockObserver(string name, Subject1 subject)
{
this.name = name;
this.subject = subject;
}
//更改不同的方法名 现实中就是这样的,方法名本就不一定相同
public void CloseStock()
{
Console.WriteLine("{0} ,{1},关闭股票",subject.SubjectState,name);
}
}
class NBAObserver
{
protected string name;
protected Subject1 subject;
public NBAObserver(string name, Subject1 subject)
{
this.name = name;
this.subject = subject;
}
//更改不同的方法名
public void CloseNBA()
{
Console.WriteLine("{0} ,{1},关闭NBA",subject.SubjectState, name);
}
}
class Program
{
/// <summary>
/// 客户端代码
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Boss boss = new Boss();
StockObserver stockObserver = new StockObserver("小林", boss);
NBAObserver nBAObserver = new NBAObserver("小周", boss);
//将两种不同的方法委托给“老板”的“更新”
boss.Update += new EventHandler(stockObserver.CloseStock);
boss.Update += new EventHandler(nBAObserver.CloseNBA);
boss.SubjectState = "老板回来了";
boss.Notify();
}
}
结果显示