C# 观察者模式实例介绍
程序员文章站
2023-11-05 20:59:40
观察者模式 观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当一个对象改变需要同时改变其他对...
观察者模式
观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当一个对象改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变的时候,应该考虑使用观察者模式。
观察者结构图:
使用场景:老板回来通知员工需要进入工作状态。
定义观察者的抽象类:
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("主人被惊醒");
}
}
}
观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者。当一个对象改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变的时候,应该考虑使用观察者模式。
观察者结构图:
使用场景:老板回来通知员工需要进入工作状态。
定义观察者的抽象类:
复制代码 代码如下:
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("主人被惊醒");
}
}
}
上一篇: JS中的一些常用的函数式编程术语