认识观察者模式(设计模式)[转载]

认识观察者模式 ( 设计模式 )
-、开题
 
设计模式就好比 天屠龙记里的兵法书武穆遗书哦,看了设计模式就会惊呼, 软件设计中 你已经在不知不觉使用,或者碰到了但尚未解决的,或者至今还没意识到的问题,上边都有了经验总结 ; 学习了想必事半功倍,具体还要在实践中不断尝试。
       设计模式一书已经被存储到大家知识库里并且逐步重视起来基础上, 这次我们来认识和讨论一下观察者模式,
    观察者模式:
     这里不多说,空间留给大家,可以从观察者模式的背景、意图、适用范围、优点、缺点、最好结合例子谈谈。
 
二讨论
Charley Chen 跟贴 :
实现观察者模式有很多形式,比较直观的一种是使用一种 注册 —— 通知 —— 撤销注册 的形式。下面的三个图详细的描述了这样一种过程:
1 :观察者( Observer )将自己注册到被观察对象( Subject )中,被观察对象将观察者存放在一个容器( Container )里。


2 :被观察对象发生了某种变化(如图中的 AskPriceChanged ),从容器中得到所有注册过的观察者,将变化通知观察者。
 
此主题相关图片如下:

3 :观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。
 
此主题相关图片如下:

观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现 —— 这一点为程序提供了更大的灵活性。
(一)通过别名从不同角度来理解
    发布 - 订阅( Publish/Subscribe )模式:状态变更的动作基本上是由被观察者发出,因此这个别名比观察者更加贴切 
    模型 - 视图( Model/View )模式:该模式重要的应用场合,也是最为适合的应用场合,常常作为示例
    - 监听器( Source/Listener )模式:?
    从属者( Dependents )模式:?
(二) C#.NET 中可以通过 Delegate Event 机制简化 Observer 模式
     详见下,对于 .NET 还不是很熟,例子摘录自 C# 设计模式
(三) Java 中内建了类 java.util.Observerable 和接口 java.util.Observer ,是对 Observer 的简单实现
        详见下,链了一篇介绍
四、  C#中的DelegateEvent
实际上在 C# 中实现 Observer 模式没有这么辛苦, .NET 中提供了 Delegate Event 机制,我们可以利用这种机制简化 Observer 模式。关于 Delegate Event 的使用方法请参考相关文档。改进后的 Observer 模式实现如下:
// Observer pattern -- Structural example  
using  System;

//Delegate
delegate  void  UpdateDelegate(); 

//Subject
class  Subject
{
  
public  event  UpdateDelegate UpdateHandler;
  
  
// Methods
   public  void  Attach( UpdateDelegate ud )
  
{
    UpdateHandler += ud;
  }

  
public  void  Detach( UpdateDelegate ud )
  
{
    UpdateHandler -= ud;
  }
  
  
public  void  Notify()
  
{
    
if (UpdateHandler !=  null ) UpdateHandler();
  }

}

//ConcreteSubject
class  ConcreteSubject : Subject
{
  
// Fields
   private  string  subjectState;

  
// Properties
   public  string  SubjectState
  
{
    
get return  subjectState; }
    
set { subjectState = value; }
  }
}

// "ConcreteObserver"
class  ConcreteObserver
{
  
// Fields
   private  string  name;
  
private  string  observerState;
  
private  ConcreteSubject subject;

  
// Constructors
   public  ConcreteObserver( ConcreteSubject subject,  
    
string  name )
  
{
    
this .subject = subject;
    
this .name = name;
  }

  
// Methods
   public  void  Update()
  
{
    observerState = subject.SubjectState;
    Console.WriteLine( "Observer {0}'s new state is {1}",
      name, observerState );
  }

  
// Properties
   public  ConcreteSubject Subject
  
{
    
get  return  subject; }
    
set  { subject = value; }
  }
}

// "ConcreteObserver"
class  AnotherObserver
{
  
// Methods
   public  void  Show()
  
{
    Console.WriteLine("AnotherObserver got an Notification!");
  }
}

public  class  Client

  
public  static  void  Main( string [] args)
  

    ConcreteSubject s = 
new  ConcreteSubject();
    ConcreteObserver o1 = 
new  ConcreteObserver(s, "1");
    ConcreteObserver o2 = 
new  ConcreteObserver(s, "2");
    AnotherObserver o3 = 
new  AnotherObserver();
    
    s.Attach(
new  UpdateDelegate(o1.Update));
    s.Attach(
new  UpdateDelegate(o2.Update));
    s.Attach(
new  UpdateDelegate(o3.Show));

    s.SubjectState = "ABC";
    s.Notify();

    Console.WriteLine("--------------------------");
    s.Detach(
new  UpdateDelegate(o1.Update));

    s.SubjectState = "DEF";
    s.Notify();
  }
}
其中,关键的代码如下:
delegate  void  UpdateDelegate(); 
定义一个 Delegate ,用来规范函数结构。不管是 ConcreteObserver 类的 Update 方法还是 AnotherObserver 类的 Show 方法都符合该 Delegate 。这不象用 Observer 接口来规范必须使用 Update 方法那么严格。只要符合 Delegate 所指定的方法结构的方法都可以在后面被事件所处理。
public  event  UpdateDelegate UpdateHandler;
定义一个事件,一旦触发,可以调用一组符合 UpdateDelegate 规范的方法。
   public  void  Attach( UpdateDelegate ud )
  
{
    UpdateHandler += ud;
  }
订阅事件。只要是一个满足 UpdateDelegate 的方法,就可以进行订阅操作(如下所示)。
    s.Attach( new  UpdateDelegate(o1.Update));
    s.Attach(
new  UpdateDelegate(o2.Update));
    s.Attach(
new  UpdateDelegate(o3.Show));
Notify 方法中:
   public  void  Notify()
  
{
    
if (UpdateHandler !=  null ) UpdateHandler();
  }
只要 UpdateHandler != null (表示有订阅者),就可以触发事件( UpdateHandler() ),所有的订阅者便会接到通知。
关于事件的使用,有一点还是值得注意:
一般我们认为:全部的事件处理器都应该返回 void 并接受两个参数:第一个参数为一个对象,它代表产生事件的对象;第二个参数是从 System.EventArgs 中派生而来的类的对象。 EventArgs 是事件数据的基类,并代表了事件的细节。
摘自范亮的举例 :
  ConcreteSubject s = new ConcreteSubject();
  ConcreteObserver o1 = new ConcreteObserver(s, "1");
  ConcreteObserver o2 = 
new ConcreteObserver(s, "2");
  AnotherObserver o3 = 
new AnotherObserver();
    
  s.Attach(
new UpdateDelegate(o1.Update));
  s.Attach(
new UpdateDelegate(o2.Update));
  s.Attach(
new UpdateDelegate(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 )虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
 
 
此主题相关图片如下:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值