C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

模式设计c#--行为型--observer

名称 Observer
结构 o_observer.bmp
意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
适用性
  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

namespace  Observer_DesignPattern
{
    
using  System;
    
using  System.Collections;

    
class  Subject
    
{
        
private  ArrayList list  =   new  ArrayList();

        
private   string  strImportantSubjectData  =   " Initial " ;
        
        
public   string  ImportantSubjectData 
        
{
            
get  
            
{
                
return  strImportantSubjectData;
            }

            
set  
            
{
                strImportantSubjectData 
=  value;
            }

        }


        
public   void  Attach(Observer o)
        
{
            list.Add(o);
            o.ObservedSubject 
=   this ;
        }


        
public   void  Detach(Observer o)
        
{
            
        }


        
public   void  Notify()
        
{
            
foreach  (Observer o  in  list)        
            
{
                o.Update();
            }
            
        }

    }


    
class  ConcreteSubject : Subject
    
{
        
public   void  GetState()
        
{
            
        }


        
public   void  SetState()
        
{
            
        }
    
    }


    
abstract   class  Observer 
    
{
        
protected  Subject s;
        
public  Subject ObservedSubject 
        
{
            
get  
            
{
                
return  s;        
            }

            
set  
            
{
                s 
=  value;
            }

        }
    
        
abstract   public   void  Update();
    }


    
class  ConcreteObserver : Observer 
    
{
        
private   string  observerName;
        
        
public  ConcreteObserver( string  name)
        
{
            observerName 
=  name;
        }


        
override   public   void  Update()
        
{
            Console.WriteLine(
" In Observer {0}: data from subject = {1} "
                observerName, s.ImportantSubjectData);
        }
    
    }


    
///   <summary>
    
///     Summary description for Client.
    
///   </summary>

     public   class  Client
    
{     
        
public   static   int  Main( string [] args)
        
{          
            
//  Set up everything
            ConcreteSubject s  =   new  ConcreteSubject();
            ConcreteObserver o1 
=   new  ConcreteObserver( " first observer " );
            ConcreteObserver o2 
=   new  ConcreteObserver( " second observer " );

            s.Attach(o1);
            s.Attach(o2);

            
//  make changes to subject
            s. ImportantSubjectData  =   " This is important subject data " ;

            
//  Notify all observers
            s.Notify();            
            
return   0 ;
        }

    }

}

比较好理解的一个例子:
// Observer pattern -- Real World example  


using System;
using System.Collections;

namespace DoFactory.GangOfFour.Observer.RealWorld
{
  
  
// MainApp test application 

  
class MainApp
  
{
    
static void Main()
    
{
      
// Create investors 
      Investor s = new Investor("Sorros");
      Investor b 
= new Investor("Berkshire");

      
// Create IBM stock and attach investors 
      IBM ibm = new IBM("IBM"120.00);
      ibm.Attach(s);
      ibm.Attach(b);

      
// Change price, which notifies investors 
      ibm.Price = 120.10;
      ibm.Price 
= 121.00;
      ibm.Price 
= 120.50;
      ibm.Price 
= 120.75;

      
// Wait for user 
      Console.Read();
    }

  }


  
// "Subject" 

  
abstract class Stock
  
{
    
protected string symbol;
    
protected double price;
    
private ArrayList investors = new ArrayList();

    
// Constructor 
    public Stock(string symbol, double price)
    
{
      
this.symbol = symbol;
      
this.price = price;
    }


    
public void Attach(Investor investor)
    
{
      investors.Add(investor);
    }


    
public void Detach(Investor investor)
    
{
      investors.Remove(investor);
    }


    
public void Notify()
    
{
      
foreach (Investor investor in investors)
      
{
        investor.Update(
this);
      }

      Console.WriteLine(
"");
    }


    
// Properties 
    public double Price
    
{
      
getreturn price; }
      
set
      
{
        price 
= value;
        Notify(); 
      }

    }


    
public string Symbol
    
{
      
getreturn symbol; }
      
set{ symbol = value; }
    }

  }


  
// "ConcreteSubject" 

  
class IBM : Stock
  
{
    
// Constructor 
    public IBM(string symbol, double price)
      : 
base(symbol, price)
    
{
    }

  }


  
// "Observer" 

  
interface IInvestor
  
{
    
void Update(Stock stock);
  }


  
// "ConcreteObserver" 

  
class Investor : IInvestor
  
{
    
private string name;
    
private Stock stock;

    
// Constructor 
    public Investor(string name)
    
{
      
this.name = name;
    }


    
public void Update(Stock stock)
    
{
      Console.WriteLine(
"Notified {0} of {1}'s " +
        
"change to {2:C}", name, stock.Symbol, stock.Price);
    }


    
// Property 
    public Stock Stock
    
{
      
getreturn stock; }
      
set{ stock = value; }
    }

  }

}
 

一、 观察者(Observer)模式

观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。
四、 C#中的Delegate与Event

实际上在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()),所有的订阅者便会接到通知。

六、 观察者模式的优缺点

Observer模式的优点是实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,类别清晰,并抽象了更新接口,使得可以有各种各样不同的表示层(观察者)。

但是其缺点是每个外观对象必须继承这个抽像出来的接口类,这样就造成了一些不方便,比如有一个别人写的外观对象,并没有继承该抽象类,或者接口不对,我们又希望不修改该类直接使用它。虽然可以再应用Adapter模式来一定程度上解决这个问题,但是会造成更加复杂烦琐的设计,增加出错几率。

观察者模式的效果有以下几个优点:

(1)观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。

(2)观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。

观察者模式有下面的一些缺点:

(1)如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

(2)如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。

(3)如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

posted on 2006-01-03 16:13 梦在天涯 阅读(851) 评论(0)  编辑 收藏 引用 所属分类: Design pattern


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1797022
  • 排名 - 5

最新评论

阅读排行榜