《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:显式地指定感兴趣的改变

    技术2022-05-19  28

    示例:显式地指定感兴趣的改变 说明: 你可以扩展目标的注册接口,让各观察者注册为仅对特定事件感兴趣,以提高更新的效率。当一个事件发生时,目标仅通知那些已注册为对该事件感兴趣的观察者。 代码:   unit uAspects; interface uses     SysUtils, Classes, Dialogs; type     TAspect = (apCalcEvent1,apCalcEvent2);     TObserver = class;     RMapInfo = record         Interest:TAspect;         Observer: TObserver;     end;     PMapInfo = ^RMapInfo;     TMapList = class(TList)     private         function GetItems(Index: Integer): PMapInfo;     protected         procedure Notify(Ptr: Pointer; Action: TListNotification); override;     public         function Add(AInterest: TAspect; AObserver: TObserver): Integer;         function IndexOf(AInterest: TAspect; AObserver: TObserver): Integer;         procedure Delete(AInterest: TAspect; AObserver: TObserver);         //---         property Items[Index: Integer]: PMapInfo read GetItems;     end;     TSubject = class     private         FObservers: TMapList;         FInterest:TAspect;     public         constructor Create;         destructor Destroy; override;         //---         procedure Attach(AObserver: TObserver;AInterest:TAspect);         procedure Detach(AObserver: TObserver;AInterest:TAspect);         procedure Notify;     end;     TConcreteSubject = class(TSubject)     private         FState: Integer;     public         procedure Calc1;         procedure Calc2;         //---         property State: Integer read FState;     end;     TObserver = class     public         procedure Update(ASubject: TSubject;AInterest:TAspect); virtual; abstract;     end;     TConcreteObserver = class(TObserver)     public         procedure Update(ASubject: TSubject;AInterest:TAspect); override;     end; procedure Test; implementation procedure Test; var     ASubject: TConcreteSubject;     AObserver: TObserver; begin     ASubject := TConcreteSubject.Create;     AObserver := TConcreteObserver.Create;     try         ASubject.Attach(AObserver,apCalcEvent2);         ASubject.Calc1;         ASubject.Calc2;     finally         AObserver.Free;         ASubject.Free;     end; end; constructor TSubject.Create; begin     FObservers := TMapList.Create; end; destructor TSubject.Destroy; begin     FObservers.Free;     //---     inherited; end; procedure TSubject.Attach(AObserver: TObserver;AInterest:TAspect); begin     FObservers.Add(AInterest,AObserver); end; procedure TSubject.Detach(AObserver: TObserver;AInterest:TAspect); begin     FObservers.Delete(AInterest,AObserver); end; procedure TSubject.Notify; var     i: integer; begin     with FObservers do     begin         for i := 0 to Count - 1 do         begin             with Items[i]^ do             begin                 if Interest = FInterest then                     Observer.Update(self,Interest);             end;         end;     end; end; procedure TConcreteObserver.Update(ASubject: TSubject;AInterest:TAspect); begin     if ASubject is TConcreteSubject then     begin         with TConcreteSubject(ASubject) do             ShowMessage(IntToStr(State));     end; end; function TMapList.Add(AInterest: TAspect; AObserver: TObserver): Integer; var     pData: PMapInfo; begin     New(pData);     pData.Interest := AInterest;     pData.Observer := AObserver;     //---     Result := inherited Add(pData); end; procedure TMapList.Delete(AInterest: TAspect; AObserver: TObserver); var     AIndex:Integer; begin     AIndex := IndexOf(AInterest, AObserver);     if AIndex >= 0 then         inherited Delete(AIndex); end; function TMapList.GetItems(Index: Integer): PMapInfo; begin     Result := inherited Items[Index]; end; function TMapList.IndexOf(AInterest: TAspect; AObserver: TObserver): Integer; var     i:Integer; begin     for i := 0 to self.Count - 1 do     begin         with Self.Items[i]^ do             if (Interest = AInterest) and (Observer = AObserver) then             begin                 Result := i;                 Exit;             end;     end;     //---     Result := -1; end; procedure TMapList.Notify(Ptr: Pointer; Action: TListNotification); begin     if Action = lnDeleted then         Dispose(Ptr);     //---     inherited; end; procedure TConcreteSubject.Calc1; begin     FInterest := apCalcEvent1;     FState := FState + 1;     //---     Self.Notify; end; procedure TConcreteSubject.Calc2; begin     FInterest := apCalcEvent2;     FState := FState * 2;     //---     Self.Notify;     end; end.


    最新回复(0)