| 導購 | 订阅 | 在线投稿
分享
 
 
 

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

來源:互聯網網民  2006-01-31 23:03:32  評論

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

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公文包中有這片文章相關的代碼,歡迎下載。也希望大家給我提出改進意見。

 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
使用類方法控制實例的唯一性 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公文包中有這片文章相關的代碼,歡迎下載。也希望大家給我提出改進意見。
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有