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

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

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

 
使用行爲控制實例
  您可以使用行爲來控制文檔中的影片剪輯和圖形實例,而無需編寫 ActionScript。行爲是預先編寫的"ActionScript"腳本,它使您可以將 ActionScript 編碼的強大功能、控制能力和靈活性添加到文檔中,而不必自己創建 ...查看完整版>>使用行爲控制實例
 
在C#中使用.NETSDK創建控制實例
  介紹  在這篇教程中,我們將使用.NET架構創建一個簡單的時鍾控制示例,這個控制是一個顯示當前時間的時鍾,我們將指導讀者實現秒針並顯示鍾點數。  創建一個控制的最快的方法是從這裏拷貝一個控制示例代碼:...查看完整版>>在C#中使用.NETSDK創建控制實例
 
通過SDK函數實現WIN32應用程序的唯一實例。
//FORMMAIN.CPP#include <windows.h>#include "ExeMutex.h"static LPCSTR szAppName = TEXT("HelloWin") ;LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance,...查看完整版>>通過SDK函數實現WIN32應用程序的唯一實例。
 
基于主鍵和唯一約束的顯示索引控制
從Oracle9i開始,主鍵創建時的索引和唯一性約束可以在建表時獨立定義。隨後,約束可以被獨立drop,而索引可以保留。這是Oracle9i中對于索引增強的幾個特性之一。SQL> CREATE TABLE employees 2 ( 3 empno N...查看完整版>>基于主鍵和唯一約束的顯示索引控制
 
pb中使用winapi生成唯一的永不重複字符串(UUID)
pb中使用winapi生成唯一的永不重複字符串(UUID) pb中使用winapi生成唯一的永不重複字符串(UUID) 1、定義結構及外部函數global type uuid from structure ulong data1 uint data2 uint data3 character d...查看完整版>>pb中使用winapi生成唯一的永不重複字符串(UUID)