在面向对象的程序开发中,复制功能是非常有意义的。很多时候构造一个对象会很复杂,需要设定很多个参数,并且调用很多个方法。如果这个对象需要很多个实例,那么重复进行复杂的创建过程就非常容易出错,对于这类问题的一个很好的解决模式就是克隆系统中的已有对象,然后对其属性进行少量修改或不作修改,这就是原型模式。
当然作为克隆的实现方法一般有两种:浅拷贝(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#):
1using System;
2using System.Collections;
3
4namespace 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
2using System.Collections;
3
4namespace 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
下面看看Pascal的shallow Copy的实现:
1program 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
11uses
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 }
56procedure DellPrototype.Assign(Source: TPersistent);
57var
58aSOBJ:DellPrototype;
59begin
60// inherited;
61 aSOBJ:=DellPrototype(Source);
62 // self.AProduct:=Product.Create;
63 self.AProduct:=aSOBJ.AProduct;
64end;
65
66procedure DellPrototype.CreateComputer;
67var
68P1,P2,P3:PPart;
69begin
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);
86end;
87
88destructor DellPrototype.Destroy;
89begin
90 AProduct.Free;
91 inherited Destroy;
92end;
93
94function DellPrototype.GetComputer: Tobject;
95begin
96 result:=AProduct;
97end;
98
99{ IBMPrototype }
100procedure IBMPrototype.Assign(Source: TPersistent);
101var
102aSOBJ:IBMPrototype;
103begin
104// inherited;
105 aSOBJ:=IBMPrototype(Source);
106 // self.AProduct:=Product.Create;
107 self.AProduct:=aSOBJ.AProduct;
108end;
109
110
111
112
113procedure IBMPrototype.CreateComputer;
114var
115P1,P2,P3:PPart;
116begin
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);
133end;
134
135destructor IBMPrototype.Destroy;
136begin
137 AProduct.Free;
138 inherited Destroy;
139end;
140
141function IBMPrototype.GetComputer: Tobject;
142begin
143 result:=AProduct;
144end;
145{ Product }
146
147procedure Product.Add(APart: PPart);
148begin
149 AProduct.Add(APart);
150end;
151
152constructor Product.Create;
153begin
154 AProduct:=TList.Create;
155end;
156
157destructor Product.Destroy;
158begin
159
160 AProduct.Free;
161 inherited Destroy;
162end;
163
164procedure Product.Say;
165var
166i:integer;
167begin
168try
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;
174except
175 on EAccessViolation do
176 Writeln('Some Object had been destoried');
177end;
178end;
179var
180APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
181DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
182
183begin
184try
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;
208end.
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
11uses
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 }
56procedure DellPrototype.Assign(Source: TPersistent);
57var
58aSOBJ:DellPrototype;
59begin
60// inherited;
61 aSOBJ:=DellPrototype(Source);
62 // self.AProduct:=Product.Create;
63 self.AProduct:=aSOBJ.AProduct;
64end;
65
66procedure DellPrototype.CreateComputer;
67var
68P1,P2,P3:PPart;
69begin
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);
86end;
87
88destructor DellPrototype.Destroy;
89begin
90 AProduct.Free;
91 inherited Destroy;
92end;
93
94function DellPrototype.GetComputer: Tobject;
95begin
96 result:=AProduct;
97end;
98
99{ IBMPrototype }
100procedure IBMPrototype.Assign(Source: TPersistent);
101var
102aSOBJ:IBMPrototype;
103begin
104// inherited;
105 aSOBJ:=IBMPrototype(Source);
106 // self.AProduct:=Product.Create;
107 self.AProduct:=aSOBJ.AProduct;
108end;
109
110
111
112
113procedure IBMPrototype.CreateComputer;
114var
115P1,P2,P3:PPart;
116begin
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);
133end;
134
135destructor IBMPrototype.Destroy;
136begin
137 AProduct.Free;
138 inherited Destroy;
139end;
140
141function IBMPrototype.GetComputer: Tobject;
142begin
143 result:=AProduct;
144end;
145{ Product }
146
147procedure Product.Add(APart: PPart);
148begin
149 AProduct.Add(APart);
150end;
151
152constructor Product.Create;
153begin
154 AProduct:=TList.Create;
155end;
156
157destructor Product.Destroy;
158begin
159
160 AProduct.Free;
161 inherited Destroy;
162end;
163
164procedure Product.Say;
165var
166i:integer;
167begin
168try
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;
174except
175 on EAccessViolation do
176 Writeln('Some Object had been destoried');
177end;
178end;
179var
180APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
181DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
182
183begin
184try
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;
208end.
由于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#):
1using System;
2using System.Collections;
3
4namespace 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模式还是比较简单的。2using System.Collections;
3
4namespace 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
下面我们看看如何用Pascal来实现同样功能的Deep Copy:
1program 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
11uses
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 }
57procedure DellPrototype.Assign(Source: TPersistent);
58var
59aSOBJ:DellPrototype;
60begin
61// inherited;
62 aSOBJ:=DellPrototype(Source);
63 self.AProduct:=Product.Create;
64 self.AProduct.Assign(aSOBJ.AProduct);
65end;
66
67procedure DellPrototype.CreateComputer;
68var
69P1,P2,P3:PPart;
70begin
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);
87end;
88
89destructor DellPrototype.Destroy;
90begin
91 AProduct.Free;
92 inherited Destroy;
93end;
94
95function DellPrototype.GetComputer: Tobject;
96begin
97 result:=AProduct;
98end;
99
100{ IBMPrototype }
101procedure IBMPrototype.Assign(Source: TPersistent);
102var
103aSOBJ:IBMPrototype;
104begin
105// inherited;
106 aSOBJ:=IBMPrototype(Source);
107 self.AProduct:=Product.Create;
108 self.AProduct.Assign(aSOBJ.AProduct);
109end;
110
111
112
113
114procedure IBMPrototype.CreateComputer;
115var
116P1,P2,P3:PPart;
117begin
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);
134end;
135
136destructor IBMPrototype.Destroy;
137begin
138 AProduct.Free;
139 inherited Destroy;
140end;
141
142function IBMPrototype.GetComputer: Tobject;
143begin
144 result:=AProduct;
145end;
146{ Product }
147
148procedure Product.Add(APart: PPart);
149begin
150 AProduct.Add(APart);
151end;
152
153procedure Product.Assign(Source: TPersistent);
154var
155aSOBJ:Product;
156i:integer;
157PX:array of PPart;
158begin
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;
168end;
169
170constructor Product.Create;
171begin
172 AProduct:=TList.Create;
173end;
174
175destructor Product.Destroy;
176begin
177
178 AProduct.Free;
179 inherited Destroy;
180end;
181
182procedure Product.Say;
183var
184i:integer;
185begin
186try
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;
192except
193 on EAccessViolation do
194 Writeln('Some Object had been destoried');
195end;
196end;
197var
198APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
199DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
200
201begin
202try
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;
228end.
当然同上面的Pascal实现shallow copy一样,要想实现Deep Copy必须要将我们的Product类也继承TPersistent,同时重写Assign,153~168行就是对Product类的Assign进行的重写。190行同样也是释放指针,但这次运行一下看看,不报错了!这就说明我们的Product中的TList已经不在是同一个对象了,从而实现了深度拷贝。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
11uses
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 }
57procedure DellPrototype.Assign(Source: TPersistent);
58var
59aSOBJ:DellPrototype;
60begin
61// inherited;
62 aSOBJ:=DellPrototype(Source);
63 self.AProduct:=Product.Create;
64 self.AProduct.Assign(aSOBJ.AProduct);
65end;
66
67procedure DellPrototype.CreateComputer;
68var
69P1,P2,P3:PPart;
70begin
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);
87end;
88
89destructor DellPrototype.Destroy;
90begin
91 AProduct.Free;
92 inherited Destroy;
93end;
94
95function DellPrototype.GetComputer: Tobject;
96begin
97 result:=AProduct;
98end;
99
100{ IBMPrototype }
101procedure IBMPrototype.Assign(Source: TPersistent);
102var
103aSOBJ:IBMPrototype;
104begin
105// inherited;
106 aSOBJ:=IBMPrototype(Source);
107 self.AProduct:=Product.Create;
108 self.AProduct.Assign(aSOBJ.AProduct);
109end;
110
111
112
113
114procedure IBMPrototype.CreateComputer;
115var
116P1,P2,P3:PPart;
117begin
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);
134end;
135
136destructor IBMPrototype.Destroy;
137begin
138 AProduct.Free;
139 inherited Destroy;
140end;
141
142function IBMPrototype.GetComputer: Tobject;
143begin
144 result:=AProduct;
145end;
146{ Product }
147
148procedure Product.Add(APart: PPart);
149begin
150 AProduct.Add(APart);
151end;
152
153procedure Product.Assign(Source: TPersistent);
154var
155aSOBJ:Product;
156i:integer;
157PX:array of PPart;
158begin
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;
168end;
169
170constructor Product.Create;
171begin
172 AProduct:=TList.Create;
173end;
174
175destructor Product.Destroy;
176begin
177
178 AProduct.Free;
179 inherited Destroy;
180end;
181
182procedure Product.Say;
183var
184i:integer;
185begin
186try
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;
192except
193 on EAccessViolation do
194 Writeln('Some Object had been destoried');
195end;
196end;
197var
198APrototype,BPrototype,CPrototype,DPrototype:TPrototype;
199DELLProduct,DELLShallowProduct,IBMProduct,IBMShallowProduct:Product;
200
201begin
202try
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;
228end.
用原型模式能根据需要克隆类,这样,在运行时就可以添加或删除类。根据程序运行情况,可以在运行时更改一个类的内部数据表示,也可以在运行时指定新对象而无需创建一个新类。
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。