观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。
(一)通过别名从不同角度来理解
发布-订阅(Publish/Subscribe)模式:状态变更的动作基本上是由被观察者发出,因此这个别名比观察者更加贴切
模型-视图(Model/View)模式:该模式重要的应用场合,也是最为适合的应用场合,常常作为示例
源-监听器(Source/Listener)模式:?
从属者(Dependents)模式:?
(二)C#.NET中可以通过Delegate与Event机制简化Observer模式
详见下,对于.NET还不是很熟,例子摘录自C#设计模式
(三)Java中内建了类java.util.Observerable和接口java.util.Observer,是对Observer的简单实现
详见下,链了一篇介绍
实际上在C#中实现Observer模式没有这么辛苦,.NET中提供了Delegate与Event机制,我们可以利用这种机制简化Observer模式。关于Delegate与Event的使用方法请参考相关文档。改进后的Observer模式实现如下:
//Observerpattern--Structuralexample
usingSystem;
//Delegate
delegatevoidUpdateDelegate();
//Subject
classSubject
{
publiceventUpdateDelegateUpdateHandler;
//Methods
publicvoidAttach(UpdateDelegateud)
{
UpdateHandler+=ud;
}
publicvoidDetach(UpdateDelegateud)
{
UpdateHandler-=ud;
}
publicvoidNotify()
{
if(UpdateHandler!=null)UpdateHandler();
}
}
//ConcreteSubject
classConcreteSubject:Subject
{
//Fields
privatestringsubjectState;
//Properties
publicstringSubjectState
{
get{returnsubjectState;}
set{subjectState=value;}
}
}
//"ConcreteObserver"
classConcreteObserver
{
//Fields
privatestringname;
privatestringobserverState;
privateConcreteSubjectsubject;
//Constructors
publicConcreteObserver(ConcreteSubjectsubject,
stringname)
{
this.subject=subject;
this.name=name;
}
//Methods
publicvoidUpdate()
{
observerState=subject.SubjectState;
Console.WriteLine("Observer{0}'snewstateis{1}",
name,observerState);
}
//Properties
publicConcreteSubjectSubject
{
get{returnsubject;}
set{subject=value;}
}
}
//"ConcreteObserver"
classAnotherObserver
{
//Methods
publicvoidShow()
{
Console.WriteLine("AnotherObservergotanNotification!");
}
}
publicclassClient
{
publicstaticvoidMain(string[]args)
{
ConcreteSubjects=newConcreteSubject();
ConcreteObservero1=newConcreteObserver(s,"1");
ConcreteObservero2=newConcreteObserver(s,"2");
AnotherObservero3=newAnotherObserver();
s.Attach(newUpdateDelegate(o1.Update));
s.Attach(newUpdateDelegate(o2.Update));
s.Attach(newUpdateDelegate(o3.Show));
s.SubjectState="ABC";
s.Notify();
Console.WriteLine("--------------------------");
s.Detach(newUpdateDelegate(o1.Update));
s.SubjectState="DEF";
s.Notify();
}
}
其中,关键的代码如下:
delegatevoidUpdateDelegate();
定义一个Delegate,用来规范函数结构。不管是ConcreteObserver类的Update方法还是AnotherObserver类的Show方法都符合该Delegate。这不象用Observer接口来规范必须使用Update方法那么严格。只要符合Delegate所指定的方法结构的方法都可以在后面被事件所处理。
publiceventUpdateDelegateUpdateHandler;
定义一个事件,一旦触发,可以调用一组符合UpdateDelegate规范的方法。
publicvoidAttach(UpdateDelegateud)
{
UpdateHandler+=ud;
}
订阅事件。只要是一个满足UpdateDelegate的方法,就可以进行订阅操作(如下所示)。
s.Attach(newUpdateDelegate(o1.Update));
s.Attach(newUpdateDelegate(o2.Update));
s.Attach(newUpdateDelegate(o3.Show));
在Notify方法中:
publicvoidNotify()
{
if(UpdateHandler!=null)UpdateHandler();
}
只要UpdateHandler != null(表示有订阅者),就可以触发事件(UpdateHandler()),所有的订阅者便会接到通知。
关于事件的使用,有一点还是值得注意:
一般我们认为:全部的事件处理器都应该返回void并接受两个参数:第一个参数为一个对象,它代表产生事件的对象;第二个参数是从System.EventArgs中派生而来的类的对象。EventArgs是事件数据的基类,并代表了事件的细节。
摘自范亮的举例:
ConcreteSubjects=newConcreteSubject();
ConcreteObservero1=newConcreteObserver(s,"1");
ConcreteObservero2=newConcreteObserver(s,"2");
AnotherObservero3=newAnotherObserver();
s.Attach(newUpdateDelegate(o1.Update));
s.Attach(newUpdateDelegate(o2.Update));
s.Attach(newUpdateDelegate(o3.Show));
如果o1,o2,o3有统一的接口去响应主题的UpdateHandler事件,那就可以去实现(继承)同一接口IObserver,编程会变的更加简练,当然这是锦上天花的事,例子已经能够说明观察者模式的思想.
下面我就随便谈谈观察者模式的背景、意图、适用范围、优点、缺点...
先谈背景:
还是举个列子
A类
Class A
{
function funA()
{
}
}
B类
Class B
{
function funB()
{
}
}
C类
Class C
{
function funC()
{
A.funA();
B.funB();
}
}
如果观察者模式可以总结成下面的应用:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。(摘自新版设计模式手册[C#].pdf)
那上边的例子是否看成观察者模式的最原始的一种呢?
优点:
是实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,类别清晰,并抽象了更新接口,使得可以有各种各样不同的表示层
缺点:
如果1对N的N很大时,花销较大。
三:总结
观察者模式的讨论先告一段落,主要还要在实践中慢慢体会.
1.在分层设计中,同层类的交互,就是横向调用比如在Bussiness层,如果有当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新的,我们可以尝试观察者模式,从而降低类之间的耦合性,我
写的例子是一种强耦合的,一定程度上讲破坏了类的高内聚低耦合及封闭原则.
2.C#编程中Delegate-Event就是很好的观察者模式原形,我们要多用它.
以下摘自C#设计模式一书,讲的蛮好:
观察者模式的效果有以下几个优点:
(1)观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(2)观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的一些缺点:
(1)如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
(2)如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。
(3)如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
相关推荐
Qt设计模式之观察者模式
设计模式之观察者模式Java版本实现和UML类设计图
设计模式--观察者模式java例子
面向对象23种设计模式之观察者模式,简单明了。面向对象23种设计模式之观察者模式,简单明了。
观察者模式设计,观察者模式设计观察者模式设计观察者模式设计,
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件...
iOS 设计模式 观察者模式
java 设计模式 观察者模式 简单实例 包括测试test类
java观察者模式观察者模式java观察者模式观察者模式java观察者模式观察者模式
观察者模式及实例,适合初学者阅读 。。。。。。。。。。。。。。。
设计模式-观察者模式(讲解及其实现代码)
对应的博客链接:http://blog.csdn.net/t1234xy4/article/details/52432559#
用观察者设计模式写的一个小demo,可以参考下(android中listview的BaseAdapter使用的就是观察者模式)
结合微信公众号讲解观察者模式,生动形象,关键是上手快啊
设计模式 中的 单例模式和观察者模式;以简单实例说明单例模式和观察者模式
软件设计模式观察者模式
用观察者模式设计一个交通信号灯调度系统,有需要的朋友可以参考下。这是本人写一篇有关于Java中设计模式,多线程调度的一个Demo吧,本人水平有限,望各位博友批评指正。此Demo实现了现实交通信号灯调度车辆通行的功能,...
设计模式:观察者模式java和javabean