在面向对象的程序开发中,复制功能是非常有意义的。很多时候构造一个对象会很复杂,需要设定很多个参数,并且调用很多个方法。如果这个对象需要很多个实例,那么重复进行复杂的创建过程就非常容易出错,对于这类问题的一个很好的解决模式就是克隆系统中的已有对象,然后对其属性进行少量修改或不作修改,这就是原型模式。
当然作为克隆的实现方法一般有两种:浅拷贝(shallow copy)与深拷贝(deep copy)。至于什么是shallow copy,什么是deep copy ?请查找相关资料,这里不累诉了。
下面我们看看Prototype模式的UML图:
抽象原型(Prototype)角色:这是一个抽象角色,这里为ComputerPrototype类,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。
具体原型(Concrete Prototype)角色:被复制的对象,这里为DELLPrototype,IBMPrototype类。此角色需要实现抽象原型角色所要求的接口。
这里我们用到了上章Builder模式举的例子,当然做了一些简化(把具体构造过程合并为了各自的构造函数)。
我们来看看shallow copy和deep copy两种不同形式的Prototype模式实现,具体代码如下(C#):
1.Shallow Copy(C#):
1
using System;
2
using System.Collections;
3
4
namespace PrototypeShallowCopy
5
{
6
/// <summary>
7
///============== Program Description==============
8
///Name:PrototypeShallowCopy.cs
9
///Objective:PrototypeShallowCopy
10
///Date:2006-04-30
11
///Written By coffee.liu
12
///================================================
13
/// </summary>
14
class Class1
15
{
16
/// <summary>
17
/// 应用程序的主入口点。
18
/// </summary>
19
[STAThread]
20
static void Main(string[] args)
21
{
22
Hashtable PH1,PH2,PH3,PH4;
23
DellPrototype P1=new DellPrototype();
24
PH1=(P1.GetComputer()) as Hashtable;//得到P1的Hashtable
25
DellPrototype P2=(DellPrototype)P1.Clone();
26
PH2=(P2.GetComputer()) as Hashtable;//得到克隆P2的Hashtable
27
Console.WriteLine("Dell Computers
..");
28
Console.WriteLine("Board:"+Convert.ToString(PH2["Board"]));
29
Console.WriteLine("CPU:"+Convert.ToString(PH2["CPU"]));
30
Console.WriteLine("Menory:"+Convert.ToString(PH2["Menory"]));
31
if (PH1==PH2)
32
Console.WriteLine("we are the same HashTable");//查看潜表拷贝的效果
33
///////////
34
IBMPrototype P3=new IBMPrototype();
35
PH3=(P3.GetComputer()) as Hashtable;//得到P3的Hashtable
36
IBMPrototype P4=(IBMPrototype)P3.Clone();
37
PH4=(P4.GetComputer()) as Hashtable;//得到克隆P4的Hashtable
38
Console.WriteLine("Dell Computers
..");
39
Console.WriteLine("Board:"+Convert.ToString(PH4["Board"]));
40
Console.WriteLine("CPU:"+Convert.ToString(PH4["CPU"]));
41
Console.WriteLine("Menory:"+Convert.ToString(PH4["Menory"]));
42
if (PH3==PH4)
43
Console.WriteLine("we are the same HashTable");//查看潜表拷贝的效果
44
45
46
}
47
}
48
//abstractPrototype
49
abstract class ComputerPrototype:ICloneable
50
{
51
abstract public Object GetComputer();
52
ICloneable 成员
61
}
62
class DellPrototype:ComputerPrototype
63
{
64
private Hashtable myHashTable;
65
public DellPrototype()
66
{
67
myHashTable=new Hashtable();
68
myHashTable.Add("Board","DellBoard");
69
myHashTable.Add("CPU","Intel");
70
myHashTable.Add("Menory","DellMenory");
71
}
72
73
public override Object GetComputer()
74
{
75
return myHashTable;
76
}
77
ICloneable 成员
86
}
87
class IBMPrototype:ComputerPrototype
88
{
89
private Hashtable myHashTable;
90
public IBMPrototype()
91
{
92
myHashTable=new Hashtable();
93
myHashTable.Add("Board","IBMBoard");
94
myHashTable.Add("CPU","Intel");
95
myHashTable.Add("Menory","IBMMenory");
96
}
97
public override Object GetComputer()
98
{
99
return myHashTable;
100
}
101
ICloneable 成员
109
}
110
111
}
112
using System;2
using System.Collections;3

4
namespace PrototypeShallowCopy5
{6
/// <summary>7
///============== Program Description==============8
///Name:PrototypeShallowCopy.cs9
///Objective:PrototypeShallowCopy 10
///Date:2006-04-3011
///Written By coffee.liu12
///================================================13
/// </summary>14
class Class115
{16
/// <summary>17
/// 应用程序的主入口点。18
/// </summary>19
[STAThread]20
static void Main(string[] args)21
{22
Hashtable PH1,PH2,PH3,PH4;23
DellPrototype P1=new DellPrototype();24
PH1=(P1.GetComputer()) as Hashtable;//得到P1的Hashtable25
DellPrototype P2=(DellPrototype)P1.Clone();26
PH2=(P2.GetComputer()) as Hashtable;//得到克隆P2的Hashtable27
Console.WriteLine("Dell Computers
..");28
Console.WriteLine("Board:"+Convert.ToString(PH2["Board"]));29
Console.WriteLine("CPU:"+Convert.ToString(PH2["CPU"]));30
Console.WriteLine("Menory:"+Convert.ToString(PH2["Menory"]));31
if (PH1==PH2)32
Console.WriteLine("we are the same HashTable");//查看潜表拷贝的效果33
///////////34
IBMPrototype P3=new IBMPrototype();35
PH3=(P3.GetComputer()) as Hashtable;//得到P3的Hashtable36
IBMPrototype P4=(IBMPrototype)P3.Clone();37
PH4=(P4.GetComputer()) as Hashtable;//得到克隆P4的Hashtable38
Console.WriteLine("Dell Computers
..");39
Console.WriteLine("Board:"+Convert.ToString(PH4["Board"]));40
Console.WriteLine("CPU:"+Convert.ToString(PH4["CPU"]));41
Console.WriteLine("Menory:"+Convert.ToString(PH4["Menory"])); 42
if (PH3==PH4)43
Console.WriteLine("we are the same HashTable");//查看潜表拷贝的效果44

45

46
}47
}48
//abstractPrototype49
abstract class ComputerPrototype:ICloneable50
{51
abstract public Object GetComputer();52
ICloneable 成员61
}62
class DellPrototype:ComputerPrototype63
{64
private Hashtable myHashTable;65
public DellPrototype()66
{67
myHashTable=new Hashtable();68
myHashTable.Add("Board","DellBoard");69
myHashTable.Add("CPU","Intel");70
myHashTable.Add("Menory","DellMenory");71
}72

73
public override Object GetComputer()74
{75
return myHashTable;76
}77
ICloneable 成员86
}87
class IBMPrototype:ComputerPrototype88
{89
private Hashtable myHashTable;90
public IBMPrototype()91
{92
myHashTable=new Hashtable();93
myHashTable.Add("Board","IBMBoard");94
myHashTable.Add("CPU","Intel");95
myHashTable.Add("Menory","IBMMenory");96
}97
public override Object GetComputer()98
{99
return myHashTable;100
}101
ICloneable 成员109
}110

111
}112

下面看看Pascal的shallow Copy的实现:
1
program Prototype;
2
3
//============== Program Description==============
4
//Name:Prototype.dpr
5
//Objective:Prototype
6
//Date:2006-05-01
7
//Written By coffee.liu
8
//================================================
9
{$APPTYPE CONSOLE}
10
11
uses
12
SysUtils,Classes;
13
//零件
14
type Part=record
15
Name:string;
16
Valual:string;
17
end;
18
PPart=^Part;
19
//具体产品
20
type Product=class
21
private
22
AProduct:TList;
23
public
24
constructor Create;
25
procedure Add(APart:PPart);
26
procedure Say();
27
destructor Destroy();override;
28
end;
29
//建造者
30
type TPrototype=class(TPersistent)
31
procedure CreateComputer;virtual;abstract;
32
function GetComputer:Tobject;virtual;abstract;
33
end;
34
//具体建造者
35
type DellPrototype=class(TPrototype)
36
private AProduct:Product;
37
public
38
procedure CreateComputer;override;
39
function GetComputer:Tobject;override;
40
// constructor Create();
41
destructor Destroy();override;
42
procedure Assign(Source:TPersistent);override;
43
44
end;
45
//具体建造者
46
type IBMPrototype=class(TPrototype)
47
private AProduct:Product;
48
public
49
procedure CreateComputer;override;
50
function GetComputer:Tobject;override;
51
// constructor Create();
52
destructor Destroy();override;
53
procedure Assign(Source:TPersistent);override;
54
end;
55
{ DellPrototype }
56
procedure DellPrototype.Assign(Source: TPersistent);
57
var
58
aSOBJ:DellPrototype;
59
begin
60
// inherited;
61
aSOBJ:=DellPrototype(Source);
62
// self.AProduct:=Product.Create;
63
self.AProduct:=aSOBJ.AProduct;
64
end;
65
66
procedure DellPrototype.CreateComputer;
67
var
68
P1,P2,P3:PPart;
69
begin
70
inherited;
71
AProduct:=Product.Create;
72
new(P1); //创建指针,以下同
73
P1^.Name:='DELL';
74
P1^.Valual:='Board';
75
AProduct.Add(p1);
76
///////////
77
new(P2);
78
P2^.Name:='DELL';
79
P2^.Valual:='Cpu';
80
AProduct.Add(p2);
81
/////////////
82
new(P3);
83
P3^.Name:='DELL';
84
P3^.Valual:='Menory';
85
AProduct.Add(p3);
86
end;
87
88
destructor DellPrototype.Destroy;
89
begin
90
AProduct.Free;
91
inherited Destroy;
92
end;
93
94
function DellPrototype.GetComputer: Tobject;
95
begin
96
result:=AProduct;
97
end;
98
99
{ IBMPrototype }
100
procedure IBMPrototype.Assign(Source: TPersistent);
101
var
102
aSOBJ:IBMPrototype;
103
begin
104
// inherited;
105
aSOBJ:=IBMPrototype(Source);
106
// self.AProduct:=Product.Create;
107
self.AProduct:=aSOBJ.AProduct;
108
end;
109
110
111
112
113
procedure IBMPrototype.CreateComputer;
114
var
115
P1,P2,P3:PPart;
116
begin
117
inherited;
118
AProduct:=Product.Create;
119
new(P1);
120
P1^.Name:='IBM';
121
P1^.Valual:='Board';
122
AProduct.Add(p1);
123
//////////////
124
new(P2);
125
P2^.Name:='IBM';
126
P2^.Valual:='Cpu';
127
AProduct.Add(p2);
128
/////////////
129
new(P3);
130
P3^.Name:='IBM';
131
P3^.Valual:='Menory';
132
AProduct.Add(p3);
133
end;
134
135
destructor IBMPrototype.Destroy;
136
begin
137
AProduct.Free;
138
inherited Destroy;
139
end;
140
141
function IBMPrototype.GetComputer: Tobject;
142
begin
143
result:=AProduct;
144
end;
145
{ Product }
146
147
procedure Product.Add(APart: PPart);
148
begin
149
AProduct.Add(APart);
150
end;
151
152
constructor Product.Create;
153
begin
154
AProduct:=TList.Create;
155
end;
156
157
destructor Product.Destroy;
158
begin
159
160
AProduct.Free;
161
inherited Destroy;
162
end;
163
164
procedure Product.Say;
165
var
166
i:integer;
167
begin
168
try
169
for i:=0 to AProduct.Count-1 do
170
begin
171
Writeln(string(PPart(AProduct.Items[i])^.Name)+':'+PPart(AProduct.Items[i])^.Valual);
172
Dispose(PPart(AProduct.Items[i]));//释放指针
173
end;
174
except
175
on EAccessViolation do
176
Writeln('Some Object had been destoried');
177
end;
178
end;
179
var
180
APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
181
DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
182
183
begin
184
try
185
APrototype:=DellPrototype.Create;
186
APrototype.CreateComputer;
187
DELLProduct:=Product(APrototype.GetComputer);
188
DELLProduct.Say;
189
////////////
190
BPrototype:=DellPrototype.Create;
191
BPrototype.Assign(APrototype);
192
DELLShallowProduct:=Product(BPrototype.GetComputer);
193
DELLShallowProduct.Say;
194
//////////////
195
CPrototype:=IBMPrototype.Create;
196
CPrototype.CreateComputer;
197
IBMProduct:=Product(CPrototype.GetComputer);
198
IBMProduct.Say;
199
//////////////
200
DPrototype:=IBMPrototype.Create;
201
DPrototype.Assign(CPrototype);
202
IBMShallowProduct:=Product(DPrototype.GetComputer);
203
IBMShallowProduct.Say;
204
finally
205
DELLProduct.Free;
206
IBMProduct.Free;
207
end;
208
end.
program Prototype;2

3
//============== Program Description==============4
//Name:Prototype.dpr5
//Objective:Prototype6
//Date:2006-05-017
//Written By coffee.liu8
//================================================9
{$APPTYPE CONSOLE}10

11
uses12
SysUtils,Classes;13
//零件14
type Part=record15
Name:string;16
Valual:string;17
end;18
PPart=^Part;19
//具体产品20
type Product=class21
private22
AProduct:TList;23
public 24
constructor Create;25
procedure Add(APart:PPart);26
procedure Say();27
destructor Destroy();override;28
end;29
//建造者30
type TPrototype=class(TPersistent)31
procedure CreateComputer;virtual;abstract;32
function GetComputer:Tobject;virtual;abstract;33
end;34
//具体建造者35
type DellPrototype=class(TPrototype)36
private AProduct:Product;37
public38
procedure CreateComputer;override;39
function GetComputer:Tobject;override;40
// constructor Create();41
destructor Destroy();override;42
procedure Assign(Source:TPersistent);override;43

44
end;45
//具体建造者46
type IBMPrototype=class(TPrototype)47
private AProduct:Product;48
public49
procedure CreateComputer;override;50
function GetComputer:Tobject;override;51
// constructor Create();52
destructor Destroy();override;53
procedure Assign(Source:TPersistent);override;54
end;55
{ DellPrototype }56
procedure DellPrototype.Assign(Source: TPersistent);57
var58
aSOBJ:DellPrototype;59
begin60
// inherited;61
aSOBJ:=DellPrototype(Source);62
// self.AProduct:=Product.Create;63
self.AProduct:=aSOBJ.AProduct;64
end;65

66
procedure DellPrototype.CreateComputer;67
var68
P1,P2,P3:PPart;69
begin70
inherited;71
AProduct:=Product.Create;72
new(P1); //创建指针,以下同73
P1^.Name:='DELL';74
P1^.Valual:='Board';75
AProduct.Add(p1);76
///////////77
new(P2);78
P2^.Name:='DELL';79
P2^.Valual:='Cpu';80
AProduct.Add(p2);81
/////////////82
new(P3);83
P3^.Name:='DELL';84
P3^.Valual:='Menory';85
AProduct.Add(p3);86
end;87

88
destructor DellPrototype.Destroy;89
begin90
AProduct.Free;91
inherited Destroy;92
end;93

94
function DellPrototype.GetComputer: Tobject;95
begin96
result:=AProduct;97
end;98

99
{ IBMPrototype }100
procedure IBMPrototype.Assign(Source: TPersistent);101
var102
aSOBJ:IBMPrototype;103
begin104
// inherited;105
aSOBJ:=IBMPrototype(Source);106
// self.AProduct:=Product.Create;107
self.AProduct:=aSOBJ.AProduct;108
end;109

110

111

112

113
procedure IBMPrototype.CreateComputer;114
var115
P1,P2,P3:PPart;116
begin117
inherited;118
AProduct:=Product.Create;119
new(P1);120
P1^.Name:='IBM';121
P1^.Valual:='Board';122
AProduct.Add(p1);123
//////////////124
new(P2);125
P2^.Name:='IBM';126
P2^.Valual:='Cpu';127
AProduct.Add(p2);128
/////////////129
new(P3);130
P3^.Name:='IBM';131
P3^.Valual:='Menory';132
AProduct.Add(p3);133
end;134

135
destructor IBMPrototype.Destroy;136
begin137
AProduct.Free;138
inherited Destroy;139
end;140

141
function IBMPrototype.GetComputer: Tobject;142
begin143
result:=AProduct;144
end;145
{ Product }146

147
procedure Product.Add(APart: PPart);148
begin149
AProduct.Add(APart);150
end;151

152
constructor Product.Create;153
begin154
AProduct:=TList.Create;155
end;156

157
destructor Product.Destroy;158
begin159

160
AProduct.Free;161
inherited Destroy;162
end;163

164
procedure Product.Say;165
var166
i:integer;167
begin168
try169
for i:=0 to AProduct.Count-1 do170
begin171
Writeln(string(PPart(AProduct.Items[i])^.Name)+':'+PPart(AProduct.Items[i])^.Valual);172
Dispose(PPart(AProduct.Items[i]));//释放指针173
end;174
except175
on EAccessViolation do176
Writeln('Some Object had been destoried');177
end;178
end;179
var180
APrototype,BPrototype,CPrototype,DPrototype:TPrototype;181
DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;182

183
begin184
try185
APrototype:=DellPrototype.Create;186
APrototype.CreateComputer;187
DELLProduct:=Product(APrototype.GetComputer);188
DELLProduct.Say;189
////////////190
BPrototype:=DellPrototype.Create;191
BPrototype.Assign(APrototype);192
DELLShallowProduct:=Product(BPrototype.GetComputer);193
DELLShallowProduct.Say;194
//////////////195
CPrototype:=IBMPrototype.Create;196
CPrototype.CreateComputer;197
IBMProduct:=Product(CPrototype.GetComputer);198
IBMProduct.Say;199
//////////////200
DPrototype:=IBMPrototype.Create;201
DPrototype.Assign(CPrototype);202
IBMShallowProduct:=Product(DPrototype.GetComputer);203
IBMShallowProduct.Say;204
finally205
DELLProduct.Free;206
IBMProduct.Free;207
end;208
end.由于Delphi没有Clone方法,所以实现起来我们需要使用到一个比较特殊的类TPersistent,TPersistent除了提供了可持久性的功能以外,它还有个非常重要的虚拟方法Assign,这个方法就实现了类似于C#的clone方法,其作用就是把一个源对象的属性复制到目标对象中,于C#有所不同的是在调用Assign方法之前,需要先Create一个目标对象,然后再复制源对象。默认的TPersistent的Assign方法只是简单地调用源对象的AssignTo方法来复制属性,而TPersistent的AssignTo虚方法也只是简单地抛出一个异常。也就是说TPersistent方法并没有实现任何有意义的功能,那么对于派生自TPersistent类的对象要想提供克隆的功能都需要重载Assign或者AssignTo方法来实现自定义的复制功能。上面的56~64,100~108行就是对DellPrototype和IBMPrototype的Assign方法的重写。我们的第190行创建的BPrototype实际上并没用用到CreateComputer来初始化类,而是直接用了APtototype的值来初始化了。
为了证实我们的DellPrototype和IBMPrototype只是一个Shallow Copy,看看172行!我们把在185行创建的APrototype中的Product对象给释放掉了!而BPrototype中的Product还指向刚刚释放调的APrototype中的Product,哄哄!系统就会报EAccessViolation错误!
当然要想系统能够显示出所有对象的信息,只要把172行注释掉就OK了。
2. Deep Copy(C#):
1
using System;
2
using System.Collections;
3
4
namespace PrototypeDeepCopy
5
{
6
/// <summary>
7
///============== Program Description==============
8
///Name:PrototypeDeepCopy.cs
9
///Objective:PrototypeDeepCopy
10
///Date:2006-04-30
11
///Written By coffee.liu
12
///================================================
13
/// </summary>
14
class Class1
15
{
16
/// <summary>
17
/// 应用程序的主入口点。
18
/// </summary>
19
[STAThread]
20
static void Main(string[] args)
21
{
22
Hashtable PH1,PH2,PH3,PH4;
23
DellPrototype P1=new DellPrototype();
24
PH1=(P1.GetComputer()) as Hashtable;//得到P1的Hashtable
25
DellPrototype P2=(DellPrototype)P1.Clone();
26
PH2=(P2.GetComputer()) as Hashtable;//得到克隆P2的Hashtable
27
Console.WriteLine("Dell Computers
..");
28
Console.WriteLine("Board:"+Convert.ToString(PH2["Board"]));
29
Console.WriteLine("CPU:"+Convert.ToString(PH2["CPU"]));
30
Console.WriteLine("Menory:"+Convert.ToString(PH2["Menory"]));
31
if (PH1!=PH2)
32
Console.WriteLine("we are not the same HashTable");//查看深度复制的效果
33
///////////
34
IBMPrototype P3=new IBMPrototype();
35
PH3=(P3.GetComputer()) as Hashtable;//得到P3的Hashtable
36
IBMPrototype P4=(IBMPrototype)P3.Clone();
37
PH4=(P4.GetComputer()) as Hashtable;//得到克隆P4的Hashtable
38
Console.WriteLine("Dell Computers
..");
39
Console.WriteLine("Board:"+Convert.ToString(PH4["Board"]));
40
Console.WriteLine("CPU:"+Convert.ToString(PH4["CPU"]));
41
Console.WriteLine("Menory:"+Convert.ToString(PH4["Menory"]));
42
if (PH3!=PH4)
43
Console.WriteLine("we are not the same HashTable");//查看深度复制的效果
44
45
}
46
}
47
//abstractPrototype
48
abstract class ComputerPrototype:ICloneable
49
{
50
abstract public Object GetComputer();
51
ICloneable 成员
60
}
61
class DellPrototype:ComputerPrototype
62
{
63
private Hashtable myHashTable;
64
private DellPrototype(Hashtable HT){
65
66
this.myHashTable=(Hashtable)HT.Clone();
67
}
68
public DellPrototype()
69
{
70
myHashTable=new Hashtable();
71
myHashTable.Add("Board","DellBoard");
72
myHashTable.Add("CPU","Intel");
73
myHashTable.Add("Menory","DellMenory");
74
}
75
76
public override Object GetComputer()
77
{
78
return myHashTable;
79
}
80
ICloneable 成员
89
}
90
class IBMPrototype:ComputerPrototype
91
{
92
private Hashtable myHashTable;
93
private IBMPrototype(Hashtable HT)
94
{
95
96
this.myHashTable=(Hashtable)HT.Clone();
97
}
98
public IBMPrototype()
99
{
100
myHashTable=new Hashtable();
101
myHashTable.Add("Board","IBMBoard");
102
myHashTable.Add("CPU","Intel");
103
myHashTable.Add("Menory","IBMMenory");
104
}
105
public override Object GetComputer()
106
{
107
return myHashTable;
108
}
109
ICloneable 成员
117
}
118
}
119
当然以上Deep Copy中对HashTable的操作还只是值的复制,如果HashTable中存放的是引用类型可能还要做进一步的复制工作。用C#来实现Prototype模式还是比较简单的。
using System;2
using System.Collections;3

4
namespace PrototypeDeepCopy5
{6
/// <summary>7
///============== Program Description==============8
///Name:PrototypeDeepCopy.cs9
///Objective:PrototypeDeepCopy 10
///Date:2006-04-3011
///Written By coffee.liu12
///================================================13
/// </summary>14
class Class115
{16
/// <summary>17
/// 应用程序的主入口点。18
/// </summary>19
[STAThread]20
static void Main(string[] args)21
{22
Hashtable PH1,PH2,PH3,PH4;23
DellPrototype P1=new DellPrototype();24
PH1=(P1.GetComputer()) as Hashtable;//得到P1的Hashtable25
DellPrototype P2=(DellPrototype)P1.Clone();26
PH2=(P2.GetComputer()) as Hashtable;//得到克隆P2的Hashtable27
Console.WriteLine("Dell Computers
..");28
Console.WriteLine("Board:"+Convert.ToString(PH2["Board"]));29
Console.WriteLine("CPU:"+Convert.ToString(PH2["CPU"]));30
Console.WriteLine("Menory:"+Convert.ToString(PH2["Menory"]));31
if (PH1!=PH2)32
Console.WriteLine("we are not the same HashTable");//查看深度复制的效果33
///////////34
IBMPrototype P3=new IBMPrototype();35
PH3=(P3.GetComputer()) as Hashtable;//得到P3的Hashtable36
IBMPrototype P4=(IBMPrototype)P3.Clone();37
PH4=(P4.GetComputer()) as Hashtable;//得到克隆P4的Hashtable38
Console.WriteLine("Dell Computers
..");39
Console.WriteLine("Board:"+Convert.ToString(PH4["Board"]));40
Console.WriteLine("CPU:"+Convert.ToString(PH4["CPU"]));41
Console.WriteLine("Menory:"+Convert.ToString(PH4["Menory"])); 42
if (PH3!=PH4)43
Console.WriteLine("we are not the same HashTable");//查看深度复制的效果44

45
}46
}47
//abstractPrototype48
abstract class ComputerPrototype:ICloneable49
{50
abstract public Object GetComputer();51
ICloneable 成员60
}61
class DellPrototype:ComputerPrototype62
{63
private Hashtable myHashTable;64
private DellPrototype(Hashtable HT){65
66
this.myHashTable=(Hashtable)HT.Clone();67
}68
public DellPrototype()69
{70
myHashTable=new Hashtable();71
myHashTable.Add("Board","DellBoard");72
myHashTable.Add("CPU","Intel");73
myHashTable.Add("Menory","DellMenory");74
}75
76
public override Object GetComputer()77
{78
return myHashTable;79
}80
ICloneable 成员89
}90
class IBMPrototype:ComputerPrototype91
{92
private Hashtable myHashTable;93
private IBMPrototype(Hashtable HT)94
{95
96
this.myHashTable=(Hashtable)HT.Clone();97
}98
public IBMPrototype()99
{100
myHashTable=new Hashtable();101
myHashTable.Add("Board","IBMBoard");102
myHashTable.Add("CPU","Intel");103
myHashTable.Add("Menory","IBMMenory");104
}105
public override Object GetComputer()106
{107
return myHashTable;108
}109
ICloneable 成员117
}118
}119

下面我们看看如何用Pascal来实现同样功能的Deep Copy:
1
program PrototypeDeep;
2
3
//============== Program Description==============
4
//Name:PrototypeDeep.dpr
5
//Objective:PrototypeDeep
6
//Date:2006-05-01
7
//Written By coffee.liu
8
//================================================
9
{$APPTYPE CONSOLE}
10
11
uses
12
SysUtils,Classes;
13
//零件
14
type Part=record
15
Name:string;
16
Valual:string;
17
end;
18
PPart=^Part;
19
//具体产品
20
type Product=class(TPersistent)
21
private
22
AProduct:TList;
23
public
24
constructor Create;
25
procedure Add(APart:PPart);
26
procedure Say();
27
destructor Destroy();override;
28
procedure Assign(Source:TPersistent);override; //深度复制
29
end;
30
//建造者
31
type TPrototype=class(TPersistent)
32
procedure CreateComputer;virtual;abstract;
33
function GetComputer:Tobject;virtual;abstract;
34
end;
35
//具体建造者
36
type DellPrototype=class(TPrototype)
37
private AProduct:Product;
38
public
39
procedure CreateComputer;override;
40
function GetComputer:Tobject;override;
41
// constructor Create();
42
destructor Destroy();override;
43
procedure Assign(Source:TPersistent);override;
44
45
end;
46
//具体建造者
47
type IBMPrototype=class(TPrototype)
48
private AProduct:Product;
49
public
50
procedure CreateComputer;override;
51
function GetComputer:Tobject;override;
52
// constructor Create();
53
destructor Destroy();override;
54
procedure Assign(Source:TPersistent);override;
55
end;
56
{ DellPrototype }
57
procedure DellPrototype.Assign(Source: TPersistent);
58
var
59
aSOBJ:DellPrototype;
60
begin
61
// inherited;
62
aSOBJ:=DellPrototype(Source);
63
self.AProduct:=Product.Create;
64
self.AProduct.Assign(aSOBJ.AProduct);
65
end;
66
67
procedure DellPrototype.CreateComputer;
68
var
69
P1,P2,P3:PPart;
70
begin
71
inherited;
72
AProduct:=Product.Create;
73
new(P1); //创建指针,以下同
74
P1^.Name:='DELL';
75
P1^.Valual:='Board';
76
AProduct.Add(p1);
77
///////////
78
new(P2);
79
P2^.Name:='DELL';
80
P2^.Valual:='Cpu';
81
AProduct.Add(p2);
82
/////////////
83
new(P3);
84
P3^.Name:='DELL';
85
P3^.Valual:='Menory';
86
AProduct.Add(p3);
87
end;
88
89
destructor DellPrototype.Destroy;
90
begin
91
AProduct.Free;
92
inherited Destroy;
93
end;
94
95
function DellPrototype.GetComputer: Tobject;
96
begin
97
result:=AProduct;
98
end;
99
100
{ IBMPrototype }
101
procedure IBMPrototype.Assign(Source: TPersistent);
102
var
103
aSOBJ:IBMPrototype;
104
begin
105
// inherited;
106
aSOBJ:=IBMPrototype(Source);
107
self.AProduct:=Product.Create;
108
self.AProduct.Assign(aSOBJ.AProduct);
109
end;
110
111
112
113
114
procedure IBMPrototype.CreateComputer;
115
var
116
P1,P2,P3:PPart;
117
begin
118
inherited;
119
AProduct:=Product.Create;
120
new(P1);
121
P1^.Name:='IBM';
122
P1^.Valual:='Board';
123
AProduct.Add(p1);
124
//////////////
125
new(P2);
126
P2^.Name:='IBM';
127
P2^.Valual:='Cpu';
128
AProduct.Add(p2);
129
/////////////
130
new(P3);
131
P3^.Name:='IBM';
132
P3^.Valual:='Menory';
133
AProduct.Add(p3);
134
end;
135
136
destructor IBMPrototype.Destroy;
137
begin
138
AProduct.Free;
139
inherited Destroy;
140
end;
141
142
function IBMPrototype.GetComputer: Tobject;
143
begin
144
result:=AProduct;
145
end;
146
{ Product }
147
148
procedure Product.Add(APart: PPart);
149
begin
150
AProduct.Add(APart);
151
end;
152
153
procedure Product.Assign(Source: TPersistent);
154
var
155
aSOBJ:Product;
156
i:integer;
157
PX:array of PPart;
158
begin
159
aSOBJ:=Product(Source);
160
setlength(PX,aSOBJ.AProduct.Count);
161
for i:=0 to aSOBJ.AProduct.Count-1 do
162
begin
163
new(PX[i]);
164
PX[i]^.Name:=PPart(aSOBJ.AProduct.Items[i])^.Name;
165
PX[i]^.Valual:=PPart(aSOBJ.AProduct.Items[i])^.Valual;
166
self.AProduct.Add(PX[i]);
167
end;
168
end;
169
170
constructor Product.Create;
171
begin
172
AProduct:=TList.Create;
173
end;
174
175
destructor Product.Destroy;
176
begin
177
178
AProduct.Free;
179
inherited Destroy;
180
end;
181
182
procedure Product.Say;
183
var
184
i:integer;
185
begin
186
try
187
for i:=0 to AProduct.Count-1 do
188
begin
189
Writeln(string(PPart(AProduct.Items[i])^.Name)+':'+PPart(AProduct.Items[i])^.Valual);
190
Dispose(PPart(AProduct.Items[i]));//释放指针
191
end;
192
except
193
on EAccessViolation do
194
Writeln('Some Object had been destoried');
195
end;
196
end;
197
var
198
APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
199
DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
200
201
begin
202
try
203
APrototype:=DellPrototype.Create;
204
APrototype.CreateComputer;
205
DELLProduct:=Product(APrototype.GetComputer);
206
207
////////////
208
BPrototype:=DellPrototype.Create;
209
BPrototype.Assign(APrototype);
210
DELLShallowProduct:=Product(BPrototype.GetComputer);
211
DELLProduct.Say;
212
DELLShallowProduct.Say;
213
//////////////
214
CPrototype:=IBMPrototype.Create;
215
CPrototype.CreateComputer;
216
IBMProduct:=Product(CPrototype.GetComputer);
217
218
//////////////
219
DPrototype:=IBMPrototype.Create;
220
DPrototype.Assign(CPrototype);
221
IBMShallowProduct:=Product(DPrototype.GetComputer);
222
IBMProduct.Say;
223
IBMShallowProduct.Say;
224
finally
225
DELLProduct.Free;
226
IBMProduct.Free;
227
end;
228
end.
当然同上面的Pascal实现shallow copy一样,要想实现Deep Copy必须要将我们的Product类也继承TPersistent,同时重写Assign,153~168行就是对Product类的Assign进行的重写。190行同样也是释放指针,但这次运行一下看看,不报错了!这就说明我们的Product中的TList已经不在是同一个对象了,从而实现了深度拷贝。
program PrototypeDeep;2

3
//============== Program Description==============4
//Name:PrototypeDeep.dpr5
//Objective:PrototypeDeep6
//Date:2006-05-017
//Written By coffee.liu8
//================================================9
{$APPTYPE CONSOLE}10

11
uses12
SysUtils,Classes;13
//零件14
type Part=record15
Name:string;16
Valual:string;17
end;18
PPart=^Part;19
//具体产品20
type Product=class(TPersistent)21
private22
AProduct:TList;23
public 24
constructor Create;25
procedure Add(APart:PPart);26
procedure Say();27
destructor Destroy();override;28
procedure Assign(Source:TPersistent);override; //深度复制29
end;30
//建造者31
type TPrototype=class(TPersistent)32
procedure CreateComputer;virtual;abstract;33
function GetComputer:Tobject;virtual;abstract;34
end;35
//具体建造者36
type DellPrototype=class(TPrototype)37
private AProduct:Product;38
public39
procedure CreateComputer;override;40
function GetComputer:Tobject;override;41
// constructor Create();42
destructor Destroy();override;43
procedure Assign(Source:TPersistent);override;44

45
end;46
//具体建造者47
type IBMPrototype=class(TPrototype)48
private AProduct:Product;49
public50
procedure CreateComputer;override;51
function GetComputer:Tobject;override;52
// constructor Create();53
destructor Destroy();override;54
procedure Assign(Source:TPersistent);override;55
end;56
{ DellPrototype }57
procedure DellPrototype.Assign(Source: TPersistent);58
var59
aSOBJ:DellPrototype;60
begin61
// inherited;62
aSOBJ:=DellPrototype(Source);63
self.AProduct:=Product.Create;64
self.AProduct.Assign(aSOBJ.AProduct);65
end;66

67
procedure DellPrototype.CreateComputer;68
var69
P1,P2,P3:PPart;70
begin71
inherited;72
AProduct:=Product.Create;73
new(P1); //创建指针,以下同74
P1^.Name:='DELL';75
P1^.Valual:='Board';76
AProduct.Add(p1);77
///////////78
new(P2);79
P2^.Name:='DELL';80
P2^.Valual:='Cpu';81
AProduct.Add(p2);82
/////////////83
new(P3);84
P3^.Name:='DELL';85
P3^.Valual:='Menory';86
AProduct.Add(p3);87
end;88

89
destructor DellPrototype.Destroy;90
begin91
AProduct.Free;92
inherited Destroy;93
end;94

95
function DellPrototype.GetComputer: Tobject;96
begin97
result:=AProduct;98
end;99

100
{ IBMPrototype }101
procedure IBMPrototype.Assign(Source: TPersistent);102
var103
aSOBJ:IBMPrototype;104
begin105
// inherited;106
aSOBJ:=IBMPrototype(Source);107
self.AProduct:=Product.Create;108
self.AProduct.Assign(aSOBJ.AProduct);109
end;110

111

112

113

114
procedure IBMPrototype.CreateComputer;115
var116
P1,P2,P3:PPart;117
begin118
inherited;119
AProduct:=Product.Create;120
new(P1);121
P1^.Name:='IBM';122
P1^.Valual:='Board';123
AProduct.Add(p1);124
//////////////125
new(P2);126
P2^.Name:='IBM';127
P2^.Valual:='Cpu';128
AProduct.Add(p2);129
/////////////130
new(P3);131
P3^.Name:='IBM';132
P3^.Valual:='Menory';133
AProduct.Add(p3);134
end;135

136
destructor IBMPrototype.Destroy;137
begin138
AProduct.Free;139
inherited Destroy;140
end;141

142
function IBMPrototype.GetComputer: Tobject;143
begin144
result:=AProduct;145
end;146
{ Product }147

148
procedure Product.Add(APart: PPart);149
begin150
AProduct.Add(APart);151
end;152

153
procedure Product.Assign(Source: TPersistent);154
var155
aSOBJ:Product;156
i:integer;157
PX:array of PPart;158
begin159
aSOBJ:=Product(Source);160
setlength(PX,aSOBJ.AProduct.Count);161
for i:=0 to aSOBJ.AProduct.Count-1 do162
begin163
new(PX[i]);164
PX[i]^.Name:=PPart(aSOBJ.AProduct.Items[i])^.Name;165
PX[i]^.Valual:=PPart(aSOBJ.AProduct.Items[i])^.Valual;166
self.AProduct.Add(PX[i]);167
end;168
end;169

170
constructor Product.Create;171
begin172
AProduct:=TList.Create;173
end;174

175
destructor Product.Destroy;176
begin177

178
AProduct.Free;179
inherited Destroy;180
end;181

182
procedure Product.Say;183
var184
i:integer;185
begin186
try187
for i:=0 to AProduct.Count-1 do188
begin189
Writeln(string(PPart(AProduct.Items[i])^.Name)+':'+PPart(AProduct.Items[i])^.Valual);190
Dispose(PPart(AProduct.Items[i]));//释放指针191
end;192
except193
on EAccessViolation do194
Writeln('Some Object had been destoried');195
end;196
end;197
var198
APrototype,BPrototype,CPrototype,DPrototype:TPrototype;199
DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;200

201
begin202
try203
APrototype:=DellPrototype.Create;204
APrototype.CreateComputer;205
DELLProduct:=Product(APrototype.GetComputer);206

207
////////////208
BPrototype:=DellPrototype.Create;209
BPrototype.Assign(APrototype);210
DELLShallowProduct:=Product(BPrototype.GetComputer);211
DELLProduct.Say;212
DELLShallowProduct.Say;213
//////////////214
CPrototype:=IBMPrototype.Create;215
CPrototype.CreateComputer;216
IBMProduct:=Product(CPrototype.GetComputer);217

218
//////////////219
DPrototype:=IBMPrototype.Create;220
DPrototype.Assign(CPrototype);221
IBMShallowProduct:=Product(DPrototype.GetComputer);222
IBMProduct.Say;223
IBMShallowProduct.Say;224
finally225
DELLProduct.Free;226
IBMProduct.Free;227
end;228
end.用原型模式能根据需要克隆类,这样,在运行时就可以添加或删除类。根据程序运行情况,可以在运行时更改一个类的内部数据表示,也可以在运行时指定新对象而无需创建一个新类。
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。

浙公网安备 33010602011771号