本文主要是介绍《GOF设计模式》—原型(Prototype)—Delphi源码示例:浅拷贝和深拷贝,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
示例:浅拷贝和深拷贝
说明:
Prototype模式最困难的部分在于正确实现Clone操作。例如,当所考虑的类已经存在时就难以新增Clone操作。当类内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能会很困难。
大多数语言都对克隆对象提供了一些支持。例如,Smalltalk提供了一个copy的实现,它被所有Object的子类所继承。C++提供了一个拷贝构造器。但这些措施并不能解决“浅拷贝和深拷贝”问题。也就是说,克隆一个对象是依次克隆它的实例变量呢,还是由克隆对象和原对象共享这些变量?
浅拷贝简单并且通常也足够了。C++中的缺省拷贝构造器实现按成员拷贝,这意味着在拷贝的和原来的对象之间是共享指针的。但克隆一个结构复杂的原型通常需要深拷贝(Deepcopy),因为复制对象和原对象必须相互独立。因此你必须保证克隆对象的构件也是对原型的构件的克隆。克隆迫使你决定如果所有东西都被共享了该怎么办。
如果系统中的对象提供了Save和Load操作,那么你只需通过保存对象和立刻载入对象,就可以为Clone操作提供一个缺省实现。Save操作将该对象保存在内存缓冲区中,而Load则通过从该缓冲区中重构这个对象来创建一个复本。
代码:
unit uPrototypeClone2;
interface
uses
Classes;
type
TStateObject = class
private
FState: string;
public
//---
property State: string read FState write FState;
end;
TBaseObject = class
private
FState: string;
public
function Clone: TBaseObject; virtual; abstract;
function GetAllState: string; virtual;
//---
property State: string read FState write FState;
end;
TObjectA = class(TBaseObject)
public
function Clone: TBaseObject; override; //--浅拷贝
end;
TObjectB = class(TBaseObject)
private
FMyState: TStateObject;
procedure SetMyState(const Value: TStateObject);
public
constructor Create;
destructor Destroy; override;
//---
function Clone: TBaseObject; override; //--深拷贝
function GetAllState: string; override;
//---
property MyState: TStateObject read FMyState write SetMyState;
end;
TObjectC = class(TBaseObject)
private
FMyState: TBaseObject;
procedure SetMyState(const Value: TBaseObject);
public
constructor Create;
destructor Destroy; override;
//---
function Clone: TBaseObject; override; //--深拷贝
function GetAllState: string; override;
//---
property MyState: TBaseObject read FMyState write SetMyState;
end;
TClient = class
private
FPrototype: TBaseObject;
public
constructor Create(Prototype: TBaseObject);
destructor Destroy; override;
//---
function CreateObject: TBaseObject;
end;
implementation
function TBaseObject.GetAllState: string;
begin
Result := FState;
end;
function TObjectA.Clone: TBaseObject;
var
AObject: TObjectA;
begin
AObject := TObjectA.Create;
AObject.State := self.State;
//---
Result := AObject;
end;
constructor TObjectB.Create;
begin
inherited;
//---
FMyState := nil;
end;
destructor TObjectB.Destroy;
begin
if FMyState <> nil then
FMyState.Free;
//---
inherited;
end;
function TObjectB.Clone: TBaseObject;
var
AObject: TObjectB;
begin
AObject := TObjectB.Create;
AObject.State := self.State;
if self.MyState <> nil then
begin
AObject.MyState := TStateObject.Create;
AObject.MyState.State := self.MyState.State;
end;
//---
Result := AObject;
end;
function TObjectB.GetAllState: string;
begin
if FMyState <> nil then
Result := FState + FMyState.State
else
Result := FState;
end;
procedure TObjectB.SetMyState(const Value: TStateObject);
begin
if assigned(FMyState) then
FMyState.Free;
FMyState := Value;
end;
constructor TObjectC.Create;
begin
inherited;
//---
FMyState := nil;
end;
destructor TObjectC.Destroy;
begin
if assigned(FMyState) then
FMyState.Free;
//---
inherited;
end;
function TObjectC.Clone: TBaseObject;
var
AObject: TObjectC;
begin
AObject := TObjectC.Create;
AObject.State := self.State;
if self.MyState <> nil then
AObject.MyState := self.MyState.Clone;
//---
Result := AObject;
end;
function TObjectC.GetAllState: string;
begin
if assigned(FMyState) then
Result := FState + FMyState.GetAllState
else
Result := FState;
end;
procedure TObjectC.SetMyState(const Value: TBaseObject);
begin
if assigned(FMyState) then
FMyState.Free;
FMyState := Value;
end;
constructor TClient.Create(Prototype: TBaseObject);
begin
FPrototype := Prototype;
end;
destructor TClient.Destroy;
begin
FPrototype.Free;
//---
inherited;
end;
function TClient.CreateObject: TBaseObject;
begin
Result := FPrototype.Clone;
end;
end.
procedure TForm1.Button1Click(Sender: TObject);
var
APrototype,AObject: TBaseObject;
AClient: TClient;
begin
APrototype := TObjectA.Create;
APrototype.State := 'Prototype A';
//---
AClient := TClient.Create(APrototype);
try
AObject := AClient.CreateObject;
showmessage(AObject.GetAllState);
AObject.Free;
finally
AClient.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
APrototype: TObjectB;
AObject: TBaseObject;
AClient: TClient;
begin
APrototype := TObjectB.Create;
with APrototype do
begin
State := 'Object B';
MyState := TStateObject.Create;
MyState.State := ' 123';
end;
//---
AClient := TClient.Create(APrototype);
try
AObject := AClient.CreateObject;
showmessage(AObject.GetAllState);
AObject.Free;
finally
AClient.Free;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
APrototype: TObjectC;
AObject: TBaseObject;
AClient: TClient;
begin
APrototype := TObjectC.Create;
with APrototype do
begin
APrototype.State := 'Object C';
APrototype.MyState := TObjectA.Create;
APrototype.MyState.State := ' 123';
end;
//---
AClient := TClient.Create(APrototype);
try
AObject := AClient.CreateObject;
try
showmessage(AObject.GetAllState);
//---
with TObjectC(AObject) do
begin
if (MyState = nil) or (MyState = APrototype.MyState) then
showmessage('浅拷贝 AObject.MyState为引用')
else
showmessage('深拷贝 AObject.MyState为新对象');
end;
finally
AObject.Free;
end;
finally
AClient.Free;
end;
end;
这篇关于《GOF设计模式》—原型(Prototype)—Delphi源码示例:浅拷贝和深拷贝的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!