Delphi VCL Framework中的Notify模式

來源:互聯網
上載者:User

  在Delphi中進行UI設計時,我們會在Form上放置許多的組件,當我們更改表單的某些屬性時,其上所有組件的相應屬性都會隨著發生改變,這是如何?的呢?這裡就使用到了Delphi VCL Framework中使用最多的一種設計模式 -- Notify模式。

  Notify模式最經常發生的應用就是在容器類中的應用。由於容器類管理了許多子類對象,因此客戶程式碼可能希望一次操作對所有容器類管理的子類對象進行特定的工作。在這種需求應用中就可以使用Notify模式,客戶程式碼只需要傳送事件給容器類,而容器類在接收到這個事件之後再逐一的通知它所管理的子類對象。

  Delphi中所有組件都是從TComponent類繼承而來的,只需要在這個類中實現通知模式,那麼它所有的子類對象便都具備了這種模式能力。我們剖析一下Delphi是如何?這個模式的。

  首先開啟TComponent所在的單元檔案Classes.pas,尋找到TComponent類的定義,我們可以看到如下代碼(注意加粗的部分)

  TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
  private
    .......
    FFreeNotifies: TList;
    .......

     procedure RemoveNotification(AComponent: TComponent);
    .......
  protected
    .......
     procedure Notification(AComponent: TComponent;
      Operation: TOperation); 
virtual ;
    .......
  public
    constructor Create(AOwner: TComponent); virtual;
    destructor Destroy; override;
    .......
     procedure FreeNotification(AComponent: TComponent);
    procedure RemoveFreeNotification(AComponent: TComponent);
    .......
  published
    property Name: TComponentName read FName write SetName stored False;
    property Tag: Longint read FTag write FTag default 0;
  end;

  當一個組件被建立時,會通過FreeNotification方法將其添加到父組件的FFreeNotifies列表中,確保父組件發生變化時自己能夠被通知到;同時父組件也被添加到自己的FFreeNotifies列表中,確保自己發生變化時能夠通知到父組件。

procedure TComponent.FreeNotification(AComponent: TComponent);
begin
  if (Owner = nil) or (AComponent.Owner <> Owner) then
  begin
    // Never acquire a reference to a component that is being deleted.
    assert(not (csDestroying in (ComponentState + AComponent.ComponentState)));
    if not Assigned(FFreeNotifies) then FFreeNotifies := TList.Create;
    if FFreeNotifies.IndexOf(AComponent) < 0 then
    begin
      FFreeNotifies.Add(AComponent);
      AComponent.FreeNotification(Self);
    end;
  end;
  Include(FComponentState, csFreeNotification);
end;

  與FreeNotification方法對應的有一個RemoveFreeNotification方法,此方法是將已經建立關聯關係的組件從彼此的FFreeNotifies列表中刪除,取消了由FreeNofifies建立的關聯。

procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
begin
  RemoveNotification(AComponent);
  AComponent.RemoveNotification(Self);
end;

  當一個組件發生變化時,則會調用Notification方法通知FreeNofifies列表中所有的組件。

procedure TComponent.Notification(AComponent: TComponent;
  Operation: TOperation);
var
  I: Integer;
begin
  if (Operation = opRemove) and (AComponent <> nil) then
    RemoveFreeNotification(AComponent);
  if FComponents <> nil then
  begin
    I := FComponents.Count - 1;
    while I >= 0 do
    begin
      TComponent(FComponents[I]).Notification(AComponent, Operation);
      Dec(I);
      if I >= FComponents.Count then
        I := FComponents.Count - 1;
    end;
  end;
end;

  與Notification方法對應的亦有一個私人的RemoveNotification方法,此方法的作用是將與之關聯的組件從FFreeNotifies列表中去除,如果沒有與之關聯的組件,則銷毀FFreeNotifies列表。

procedure TComponent.RemoveNotification(AComponent: TComponent);
begin
  if FFreeNotifies <> nil then
  begin
    FFreeNotifies.Remove(AComponent);
    if FFreeNotifies.Count = 0 then
    begin
      FFreeNotifies.Free;
      FFreeNotifies := nil;
    end;
  end;
end;

小結一下

  從TComponent類的定義代碼可以看出Delphi只將FreeNotificationRemoveFreeNotification方法公開出來,是希望我們利用這兩個方法在建立和取消組件間的關聯;而將Notification方法定義為受保護的虛方法,則為我們提供了改寫通知群組件時執行附加操作的機會。

使用時機

  •   在設計容器類時程式員想定義和外界一致的互動介面
  •   需要對一群組件執行預定義好的特定工作

應用舉例

  在編寫MIS軟體時,會涉及到一些單據的填寫,就以進貨單為例。在一張進貨單中會填寫貨品的單價、價格,我們希望在這兩個欄位的值發生變化時系統能夠自動的計算出最新的總價。在這裡,我們就可以借鑒Notify模式,將數量與單價加入到彼此的通知清單中,並編寫通知處理方法如上面講到的Notification方法。這樣,無論單價還是數量發生變化都會觸發通知事件,進而達到重新計算總價的目的。

  個人拙見,還望各位斧正。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.