关于SingleTon(单例模式的delphi实现可行性讨论)(100分)

L

lzhuan

Unregistered / Unconfirmed
GUEST, unregistred user!
singletong目的是在系统中确保只有一个实例被创建。
在创建的时候判断是否已存在该对象的实例,如果存在返回该实例,
不存在就新创建一个该对象的实例。因为这个判断逻辑要对象本身来实现。
这样java中的解决方法是把构成函数私有化,防止外界直接调用。
然后通过一个 static Pubic方法创建或直接返回该对象实例。
可是在delphi中这招就不行了,delphi中的构造函数是不可以私有化的。
这样我该怎么阻止别人直接调用create方法?
请各位高人谈谈您的看法,谢谢
 
看 delphi版的设计模式!
 
这个也看过,不过总觉得其实现过于复杂。
想看看有没有其它的解决方法
 
在Singleton类中实现一个
class procedure Create;
方法,混淆构造函数的create
 
delphi里是通过重载NewInstance来实现
 
override 父类的 Create 方法,一般override后的Create方法的第一句通常是:
begin
inherited;
....
end;
对不?你去掉begin
end间的所有代码,抛出一个异常
begin
Exception.Create('singleton cannot be create as another instance');
end;
然后写一个公有函数:function CreateInstanceOnly: TObject
外界调用这个CreateInstanceOnly来获得一个实例,这样不就得了吗?
 
model maker 里可以生成单例模式的代码,可以参考
 
这个东西,可以参看Delphi中的剪贴班Clipbrd.pas的源码,可以提供类似的实现。
通过暴露一个函数 function Clipboard: TClipboard;
来访问剪贴板。
我自己也经常这么干。
通过 Create 来限制多实例,好像一点也不优美。
如果明明知道某一个类只能有一个实例,还要去调用Create的话,那就是恶意的了。
 
这个问题是相当有用的,事实上我们也在用,有多种方法,例如用共用变量。
 
我同意薄荷的看法,还有一种方法,类工厂模式。
定义一个工厂类:
var
A: TA;
TFactory = class
function create;
begin
if not assigned(A) then
A := TA.Create;
Result := A;

end;
 
问题是很多时候不是每个人都知道某个类只有一个实例,对create做限制是很有必要的。
在团队开发里有用,自己一个人开发,怎么方便怎么弄。
 
也是哦。还有谁有高见?
 
TTest = class(XXX)
public
constructor Create;
override;
class function Instance: TTest;
...
end;

implementation
var
Test: TTest = nil;
constructor TTest.Create;
begin
// 禁止直接调用构造器
raise Exception.Create('do not create me!');
end;

class function TTest.Instance: TTest;
begin
if not Assigned(Test) then
begin
Result := inherited Create;
// 调用父类的构造器
Result.XXX := XXX;
// 这里做原本应该在构造器里面做的初始化工作
...
end
else
Result := Test;
end;
 
好像从TObject继承的类不能override Create吧,
如果用异常的话还必须指望客户处理这个异常~个人觉得不是太好
type
TSingleton = class
public
class function Create: TSingleton;
protected
constructor CreateEx;
private
fValue: Integer;
end;

TForm = ...
var
Form1: TForm1;
Singleton: TSingleton;
implementation
constructor TSingleton.CreateEx;
begin
fValue := 10;
end;

class function TSingleton.Create: TSingleton;
begin
if Singleton = nil then
Singleton := TSingleton.CreateEx;
Result := Singleton;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Singleton := TSingleton.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Singleton.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Singleton := TSingleton.Create;
ShowMessage(IntToStr(Singleton.fValue));
end;
在Button1Click事件中,不再创建新的Singleton。
 
要是哪个用户调用TSingleton.Create,而不调用Singleton.Free,会有点奇怪[:)]
在Singleton类中添加了一个fTag用来控制对象被Create的次数
TSingleton = class
public
class function Create: TSingleton;
class procedure Free;
protected
fTag: Integer;
constructor CreateEx;
destructor Destroy;
override;
private
fValue: Integer;
end;

destructor TSingleton.Destroy;
begin

inherited;
end;

class function TSingleton.Create: TSingleton;
begin
if Singleton = nil then
Singleton := TSingleton.CreateEx;
Result := Singleton;
Inc(Singleton.fTag);

end;

class procedure TSingleton.Free;
begin
Dec(Singleton.fTag);
if Singleton.fTag > 0 then
Exit;
Singleton.Destroy;
end;
。。。
procedure TForm1.Button1Click(Sender: TObject);
begin
Singleton := TSingleton.Create;
try
ShowMessage(IntToStr(Singleton.fValue));
finally
Singleton.Free;
end;
end;
 
单例模式也不适合所有的情况,比如象word或excel,基于MDI可以同时打开多个文档或数据库,起码子窗口就不适合单例模式。
 
我有一个程序,可同时打开相同结构的数据库,就不适合单例模式。
 
没有一个模式会适合所有情况,即使像new、create那么常用的创建型模式AF,也不能说适用于所有情况
就像建筑学上的角门模式,也只能说:建议除了很大的房间之外,房门应该尽量靠近墙角
 
顶部