《GOF设计模式》—原型(Prototype)—Delphi源码示例:浅拷贝和深拷贝
来源:互联网 发布:印度药品 知乎 编辑:程序博客网 时间:2024/06/05 16:54
示例:浅拷贝和深拷贝
说明:
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源码示例:浅拷贝和深拷贝
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:浅拷贝和深拷贝
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于Assign方法的拷贝
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于流操作的拷贝
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:原型接口
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于实例的原型管理器
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于原型的迷宫1
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于原型的迷宫2
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:原型接口
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:乐谱编辑器
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:电路设计编辑器
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:初始化克隆对象
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于类的原型管理器(使用TList实现)
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于类的原型管理器(使用TStringList实现)
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:基于类的原型管理器(使用TList和TObject对象服务实现)
- 《GOF设计模式》—代理(PROXY)—Delphi源码示例:更新前拷贝机制(copy-on-write)
- 《GOF设计模式》—抽象工厂(Abstract Factory)—Delphi源码示例:基于原型的工厂
- 设计模式之 原型模式(prototype)(C++实现 深拷贝 + 浅拷贝版本[bug])
- 百度面试题
- 2014/8/3 记
- PUE简介
- poj 1850(组合数学)
- [Phonegap+Sencha Touch] 移动开发22、安卓4.0.X的webview或自带浏览器中,去除输入框外面的蓝色边框
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:浅拷贝和深拷贝
- [Phonegap+Sencha Touch] 移动开发23 Android和IOS的webview点击穿透的缓解办法
- [Phonegap+Sencha Touch] 移动开发24 打包wp8.1的App,运行时输入框聚焦弹出软键盘之后,界面上移而不恢复原位的解决办法
- 如何避免length10000问题
- Linux 2.6 内核阅读笔记 信号
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:原型接口
- [Phonegap+Sencha Touch] 移动开发25 关于sencha touch在华为、红米、HTC等部分手机下hide事件失效,msgbox无法关闭的解决方案
- Disruptor使用入门
- 我和别人不和人