程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 使用類方法控制實例的唯一性

使用類方法控制實例的唯一性

編輯:Delphi

使用類方法控制實例的唯一性

  

  

CST 2005-7-29

  

  

 

  

  

文檔目的

  

  

在面向對象編程中,出於各種原因,有時我們希望控制一個類的實例僅有一個存在於內存中。例如我在編程中遇到一個實際情況,程序的配置數據保存在XML文檔中,需要寫一個XML配置文件解析類。由於讀入的數據可能很龐大,而且在程序每個模塊中都用到該解析類的實例,那麼如果每次都創建一個實例並重新讀入數據,效率就不令人滿意了。

  

  

 

  

  

 

  

  

類方法

  

  

我們可以通過類方法(Class Method)實現實例創建的控制,其實也有許多其他的方法。這裡我先介紹“類方法”的實現。

  

  

 

  

  

如下是DELPHI對類方法的定義:

  

  

A class method is a method (other than a constructor) that operates on classes instead of objects. The definition of a class method must begin with the reserved word class. For example,

 

  

  

type

  

  

  TFigure = class

  

  

  public

  

  

    class function Supports(Operation: string): Boolean; virtual;

  

  

    class procedure GetInfo(var Info: TFigureInfo); virtual;

  

  

    ...

  

  

  end;

  

  

 

  

  

The defining declaration of a class method must also begin with class. For example,

  

  

 

  

  

class procedure TFigure.GetInfo(var Info: TFigureInfo);

  

  

begin

  

  

  ...

  

  

end;

  

  

 

  

  

In the defining declaration of a class method, the identifier Self represents the class where the method is called (which could be a descendant of the class in which it is defined). If the method is called in the class C, then Self is of the type class of C. Thus you cannot use Self to access fields, properties, and normal (object) methods, but you can use it to call constructors and other class methods.

  

  

A class method can be called through a class reference or an object reference. When it is called through an object reference, the class of the object becomes the value of Self.

  

  

 

  

  

定義一個類方法就是在將一個方法生命在PUBLIC段中,並加上class前綴。這樣的方法可以由類直接調用,而不需要先創建類的實例。比如構造函數Create就是一個類方法,我們在創建對象實例的時候這樣寫:

  

  

MyObject:=TmyClass.Create;

  

  

此時的Create方法由類TmyClass調用。

  

  

 

  

  

實現方法

  

  

我們實現的目的就是不以平時的對象訪問模式調用對象

  

  

Myobject:=TmyClass.Create(self);

  

  

Try

  

  

  With Myobject do begin

  

  

//do something

  

  

  end;

  

  

finally

  

  

  FreeAndNil(Myobject);

  

  

End;

  

  

 

  

  

而是使用一個類方法GetInstance來間接獲取對象實例,這個唯一的對象實例被申明在類的單元文件內(後文回詳細說明),在GetInstance函數中判斷該實例是否被創建賦值,如果沒有,則調用構造函數創建;如果已創建,則直接返回該實例。

  

  

這裡,我們需要將構造函數Create申明在private段中,僅能由GetInstance判斷調用。TmyClass.GetInstance函數返回值為TmyClass類型的變量,如果Tmyclass繼承自Tcomponent的話,create方法需要一個Aowner參數,因此我為GetInstance增加一個Aowner參數。

  

  

 

  

  

GetInstance類方法的實現不影響類中其他方法的實現,一般我們在調試設計階段不進行類方法的考慮,而是公開需要測試的對象方法以便於調試。最後要發布類的時候,我們做如下改動:

  

  

1.        在類單元文件中,但是在類定義之外申明唯一對象變量。
  我的做法是在
  implementation
  var mySoloObject:TMyClass;

  

  

2.        隱藏構造函數
  將constructor函數申明在private段中

  

  

3.        增加一個GetInstance類方法,定義在Public段中,判斷mySoloObject是否被創建。

  

  

 

  

  

具體代碼如下:

  

  

……

  

  

//類定義

  

  

TConfigReader = class(TComponent)

  

  

        private

  

  

            FXMLDoc: TXMLDocument;       

  

  

            constructor Create(AOwner:TComponent); override;

  

  

        public

  

  

            FCtrlInfoList:TObjectList;

  

  

            function OpenXMLFile(const APath:string):boolean;

  

  

            function ReadCtrlInfoToList: Integer;

  

  

            class function GetInstance(AOwner:TComponent):TConfigReader;

  

  

        end;

  

  

//唯一對象變量

  

  

 

  

  

implementation

  

  

 

  

  

var

  

  

ConfigReaderSolo:TConfigReader;

  

  

 

  

  

//函數定義

  

  

class function TConfigReader.GetInstance(AOwner:TComponent):TConfigReader;

  

  

begin

  

  

    if ConfigReaderSolo=nil then

  

  

       ConfigReaderSolo:=TConfigReader.Create(AOwner);

  

  

    Result:=ConfigReaderSolo;

  

  

end;

  

  

 

  

  

訪問方法

  

  

做了如上修改以後,我們的類就可以實現唯一實例的判斷以及創建控制。

  

  

在主調單元中,我們想往常一樣uses類所在的unit文件,相較普通的對象訪問方式,我們采用類似如下的代碼:

  

  

TConfigReader.GetInstance(Self).MyMethod1;

  

  

TConfigReader.GetInstance(Self).MyMethod2;

  

  

MyVar:= TConfigReader.GetInstance(Self).MyFunc1;

  

  

MyObject:= TConfigReader.GetInstance(Self).Member1;

  

  

……

  

  

 

  

  

小結

  

  

對數據的隱藏、共享、保護是OO編程的優點,利用不同的數據訪問級別隱藏相應的方法、成員,可以更大限度控制數據的安全性,也可以讓程序按照我們想要的方式運行。類方法和類成員可以在對象沒有創建的時候就被訪問,因此可以越過對象本身來判斷其創建與否。定義在單元內但類外的對象變量可以全局於單元內的所有類。

  

  

 

  

  

在我的YAHOO公文包中有這片文章相關的代碼,歡迎下載。也希望大家給我提出改進意見。

  

  


 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved