C# 观察者模式实例介绍
C# 观察者模式实例介绍
发布时间:2016-12-28 来源:查字典编辑
摘要:观察者模式观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当...

观察者模式

观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当一个对象改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变的时候,应该考虑使用观察者模式。

观察者结构图:

C# 观察者模式实例介绍1

使用场景:老板回来通知员工需要进入工作状态。

定义观察者的抽象类:

复制代码 代码如下:

abstract class Observer

{

protected string name;

protected ISubject sub;

public Observer(string name, ISubject sub)

{

this.name = name;

this.sub = sub;

}

public abstract void Update();

}

看NBA直播的同事:

复制代码 代码如下:

//使用OO

class NBAObserver : Observer

{

public NBAObserver(string name, ISubject sub)

: base(name, sub)

{ }

public override void Update()

{

//throw new NotImplementedException();

Console.WriteLine("{0} {1}关闭NBA直播,继续工作!",sub.SubjectState,name);

}

}

//使用事件和委托

class NBAObserver2

{

private string name;

private ISubject2 sub;

public NBAObserver2(string name, ISubject2 sub)

{

this.name = name;

this.sub = sub;

}

public void CloseStockMarket()

{

Console.WriteLine("{0} {1}关闭NBA直播,继续工作!", sub.SubjectState, name);

}

}

看股票的同事:

复制代码 代码如下:

//使用OO

class StockObserver : Observer

{

public StockObserver(string name, ISubject sub) : base(name,sub)

{ }

public override void Update()

{

//throw new NotImplementedException();

Console.WriteLine("{0} {1}关闭股票行情,继续工作!",sub.SubjectState,name);

}

}

//使用事件和委托

class StockObserver2

{

private string name;

private ISubject2 sub;

public StockObserver2(string name, ISubject2 sub)

{

this.name = name;

this.sub = sub;

}

public void CloseNBA()

{

Console.WriteLine("{0} {1}关闭股票行情,继续工作!", sub.SubjectState, name);

}

}

上的身份是订阅者,下面定义发布者:

复制代码 代码如下:

//使用OO

interface ISubject

{

void Attach(Observer observer);

void Detach(Observer observer);

void Notify();

string SubjectState

{

get;

set;

}

}

class Boss : ISubject

{

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; }

}

}

//使用事件和委托

interface ISubject2

{

void Notify();

string SubjectState

{

get;

set;

}

}

delegate void EventHandler();

class Boss2 : ISubject2

{

public event EventHandler Update;

private string action;

public void Notify()

{

Update();

}

public string SubjectState

{

get { return action; }

set { action = value; }

}

}

主函数调用:

复制代码 代码如下:

class Program

{

static void Main(string[] args)

{

//观察者模式OO实现

Boss huhansan = new Boss();

StockObserver tongshi1 = new StockObserver("name1",huhansan);

NBAObserver tonshi2 = new NBAObserver("name2", huhansan);

huhansan.Attach(tongshi1);

huhansan.Attach(tonshi2);

huhansan.SubjectState = "我1回来了";

huhansan.Notify();

//观察者模式c#事件实现

Boss2 huhansan2 = new Boss2();

StockObserver2 tongshi3 = new StockObserver2("name3", huhansan2);

NBAObserver2 tonshi4 = new NBAObserver2("name4", huhansan2);

huhansan2.Update += new EventHandler(tongshi3.CloseNBA);

huhansan2.Update += new EventHandler(tonshi4.CloseStockMarket);

huhansan2.SubjectState = "我2回来了";

huhansan2.Notify();

Console.ReadKey();

}

}

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

1 观察者模式

一个简单的例子,比如说猫叫,老鼠跑,主人被惊醒。

在不知道观察者模式之前,我们的代码可能是这样的。

复制代码 代码如下:

//老鼠类

class Mouse

{

public void Run()

{

Console.WriteLine("老鼠跑了!");

}

}

//主人类

class Master

{

public void Wake()

{

Console.WriteLine("主人醒了!");

}

}

//猫类

class Cat

{

public void Cry ()

{

Console.WriteLine("猫叫了!");

new Mouse().Run();//猫叫的同时,调用老鼠跑的方法。

new Master().Wake();//猫叫的同时,调用主人醒的方法。

}

}

class Program

{

static void Main(string[] args)

{

Cat cat = new Cat();

cat.Cry();

Console.ReadLine();

}

}

这个代码基本上能实现所有的功能。但是,这个方法特别不利用扩展,

试想,如果,猫叫后,狗也叫,那是不是也要在猫叫的方法里重新加入狗叫的方法?

或者说,猫叫后,主人他老婆也醒了,是不是也要在猫叫的方法里加入他老婆醒的方法呢?

显然,这样的代码不利用维护,也不是面向对象的代码。

观察者模式能够很好的解决这个问题。

观察者模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并自动更新。在我们的例子中,猫和老鼠,主人,狗,主人他老婆是一对多的依赖,当猫叫时,所有依赖于它的对象都会自动执行某个操作。

观察者模式的实现,一般有下面四部分组成。

1.ISubject接口(抽象目标),含方法Notify,Register,UnRegister(名字可以自己任意取名)

2.Subject类(实体目标),实现ISubject接口,一般只有一个

3.IObservable接口(抽象观察者)。

4 Observer类(实体观察者),实现IObservable接口,一般有多个。

观察者模式中的“注册--通知--注销”图示:

1. 观察者(Observer)将自己(Regiester)注册到被观察对象(Subject)中,被观察对象将观察者放在一个容器(Container)。Container一般为Ilist,Arraylist等数据结构,存放多个IObservable接口变量。

2.当被观察对象(Subject)发生变化(如图中的AskPriceChanged)时,容器(Container)中的所有观察者(Observer)都得到通知(Notify 方法),此时观察者会自动执行某些方法。

3.当观察者不想继续观察被观察者时,可以注销(UnRegiester方法)

上面的例子中改造后变成:

1.ISubject接口:

复制代码 代码如下:

interface ISubject

{

void Notify();//主题变动时,通知虽有观察者

void Regiester(IObservable o);//观察者注册

void UnRegiester(IObservable o);//观察者取消注册,此时主题发生任何变动,观察者都不会得到通知。

}

2.Subject 类:

复制代码 代码如下:

class Cat : ISubject

{

private IList<IObservable> observers = new List<IObservable>();

public void Notify()

{

foreach (IObservable o in observers) //逐个通知观察者

{

o.Action();

}

}

public void Regiester(IObservable o)

{

if (o != null || !observers.Contains(o))

{

observers.Add(o);

}

}

public void UnRegiester(IObservable o)

{

if (observers != null && observers.Contains(o))

{

observers.Remove(o);

}

}

public void Cry()

{

Console.WriteLine("猫叫了!");

Notify();

}

}

3. IObservable 接口:

复制代码 代码如下:

interface IObservable

{

void Action();//观察者对主题变动所对应的操作

}

4.Observer类(2个,Mouse和Master)

复制代码 代码如下:

class Mouse : IObservable

{

public void Action()

{

Console.WriteLine("鼠跑了!");

}

}

class Master : IObservable

{

public void Action()

{

Console.WriteLine("主人醒了!");

}

}

5.主程序

复制代码 代码如下:

Mouse mouse = new Mouse();

Master master = new Master();

Cat cat = new Cat();

cat.Regiester(mouse);

cat.Regiester(master);

cat.Cry();

Console.ReadLine();

这样就实现了观察者模式,通过把依赖类注册到主体类中,当主体类发生变化时,所有依赖类都得到了通知。如果需要扩展,比如说象上面例子的狗也叫了,我们可以定义一个狗类,然后在主程序中把狗对象注册到猫类中就可以了。如果不想依赖于猫类,也可以通过UnRegiester方法取消绑定。

同时,这也符合设计中的高内聚,低耦合的原则。

复制代码 代码如下:

using System;

using System.Collections.Generic;

using System.Text;

namespace Sample

{

public delegate void CatCallEventHandler();

class Program

{

static void Main(string[] args)

{

Cat cat = new Cat();

Mouse mouse = new Mouse(cat);

Master master = new Master(mouse);

cat.Call();

}

}

class Cat

{

public event CatCallEventHandler catevent;

public void Call()

{

Console.WriteLine("喵喵.....");

catevent();

}

}

class Mouse

{

public event CatCallEventHandler mouseevent;

public Mouse(Cat cat)

{

cat.catevent += new CatCallEventHandler(this.MouseRun);

}

public void MouseRun()

{

Console.WriteLine("老鼠跑");

mouseevent();

}

}

class Master

{

public Master(Mouse mouse)

{

mouse.mouseevent+=new CatCallEventHandler(this.JingXing);

}

public void JingXing()

{

Console.WriteLine("主人被惊醒");

}

}

}

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新C#教程学习
热门C#教程学习
编程开发子分类