产生问题的环境:
    1)Unit1 中有类 A 继承于DBGrid,包含一个TADOQuery。
    2)窗体Form2 调用 Unit1 中类A,建立多个实例,
       窗体Form2 包含一个变量(TStringList),每建一个A的实例,就使用TStringList的AddObject方法把实例添加到列表中。
    3)类A中实现TADOQuery的方法QueryAfterScroll,遍历窗体Form2 中的实例A的列表。
   
    现在出现内容耦合,因为TADOQuery的方法QueryAfterScroll调用了窗体Form2 中的实例A的列表。问题:    请问怎样把耦合去掉?我自己想把TStringList 传入到类A中但是不知道怎么实现。    请大家帮帮忙,谢谢!

解决方案 »

  1.   

    比较简单的做法就是把你在A类中遍历Form2中的TStringList的功能,分离出来直接在Form2中实现。其实就是将A类中TADOQuery发生的 QueryAfterScroll事件暴露给外部。
    TA=class 
       ...
        procedure SetAfterScroll(const Value: TDataSetNotifyEvent);
        function GetAfterScroll: TDataSetNotifyEvent;
        public
        property AfterScroll : TDataSetNotifyEvent read GetAfterScroll write SetAfterScroll;.....
    function TA.GetAfterScroll: TDataSetNotifyEvent;
    begin
      Result := ADOQuery1.AfterScroll;
    end;procedure TA.SetAfterScroll(const Value: TDataSetNotifyEvent);
    begin
      ADOQuery1.AfterScroll := value;
    end;这样就可以再Form2中关联这个事件进行处理了。
      

  2.   


    谢谢 hawksoft 。
      
      我想复用A类,想把Form2的Tstringlist 功能写到类中,或者把Form2的Tstringlist 传递到A类中。
    没有思路。
      

  3.   


    谢谢 Corn1 。我一直在想观察者模式。以前没有用过,要好好看看。
      

  4.   

    在此再次感谢 Corn1 和 hawksoft 。 
    按照观察者模式可以解决这个问题。hawksoft 给出的方法可以使程序更加的简单和优雅。
    谢谢!
      

  5.   

    严格的讲,你这不是观察者模式。观察者模式需要一个主题,而你A类不符合主题特征。你所需要的是对A类产生的实例进行管理而已。所谓观察者模式是一对多,即若干个观察者实例观察一个被观察实例。由主题实例触发观察者所注册的事件。
    Tsubject = class
      private 
         observers: TList;
      public 
        procedure AddObserver(TObserver obj)
        procedure RemoveObserver(TObserver obj);
        procedure SomethingHappend;//在这个过程做处理,并通知观察者.
        procedure NotifyObservers;//通知观察者
          for i:=0 to observers.count-1 do
         begin
             TObserver(observers[i]).SubjectHasSomgthing(self,参数....)
         end   
    end;Tobserver = class
       public 
         procedure SubjectHasSomgthing(sender:Tsubject,参数....)
           //在这个事件里进行观察到事情进行处理
    end;为了扩展,可以把Tobserver做成接口,具体的实现由实现该接口的类进行.