包建强的开源地带
我的微软梦,实现了一半
博客园
社区
首页
新随笔
联系
管理
订阅
随笔- 289 文章- 0 评论- 1009
我也设计模式——5.Prototype
我很喜欢这个模式,因为它解决了对象赋值的问题。尤其是那个Clone方法,记忆犹新。
使用场景:当一个系统应该独立于产品的创建,构成和表示时,使用设计模式。
.NET提供了ICloneable接口,只要实现了其Clone方法,在其中执行复制对象的操作。关键就是这个Clone方法,由于对象的复杂性,分为浅复制
和深复制两种:
对于浅复制,可以使用Object的MembermiseClone方法:
public
class
A : ICloneable
{
public
object
Clone()
{
return
this
.MemberwiseClone();
}
}
但是,这样复制的对象没有任何区别。于是,可以使用如下折中的办法,
class
Program
{
static
void
Main()
{
A a1
=
new
A(
"
bjq
"
);
A a2
=
(A)a1.Clone();
a2.f1
=
"
jax
"
;
}
}
public
class
A : ICloneable
{
public
string
f1;
public
string
f2;
public
A(
string
f1)
{
this
.f1
=
f1;
}
public
object
Clone()
{
A a
=
new
A();
a.f2
=
f2;
return
a;
}
}
可以看到,对象a2虽然是a1的复制,但f1字段是不一样的。
——这里说的不一样,不是具有相同字段/属性值的两个不同指针,我只是想找出两个从外表看有区别的对象。
对于深复制,要使用序列化来实现Clone方法,从而不仅仅复制对象本身,同时连同被引用的对象一起复制,代码如下:
[Serializable]
public
class
A
{
private
string
f1;
private
string
f2;
public
A(
string
f1,
string
f2)
{
this
.f1
=
f1;
this
.f2
=
f2;
}
public
A Clone()
{
MemoryStream memoryStream
=
new
MemoryStream();
BinaryFormatter formatter
=
new
BinaryFormatter();
formatter.Serialize(memoryStream,
this
);
memoryStream.Position
=
0
;
A a
=
(A)formatter.Deserialize(memoryStream);
return
a;
}
}
这里只是说明如何正确使用串行化,而效果并不明显,如果引用一个数组,则能表现出深浅序列化的区别。
深复制在互相引用时,会陷入死循环:A引用B,B又引用A——对于此,是没有完美的解决方案的,为此,我们可以加一个didClone标记,以减少这种问题。
案例分析:
IDE中的ToolBox中各个小工具的实现,比如说Button和TextBox等,可以用原型模式实现。每个Control都要实现Clone()方法,比如说Label:
public
class
myLabel : Label, ICloneable
{
public
object
Clone()
{
myLabel ml
=
new
myLabel();
return
ml;
}
}
于是,在Form中实现如下:
public
partial
class
Form1 : Form
{
private
Hashtable ht
=
new
Hashtable();
private
string
status
=
"
Label
"
;
private
void
Form1_Load(
object
sender, EventArgs e)
{
MyLabel ml
=
new
MyLabel();
ml.Text
=
"
Hello
"
;
ht.Add(
"
Label
"
, ml);
}
private
void
button1_Click(
object
sender, EventArgs e)
{
ICloneable fc
=
(ICloneable)ht[status];
Control c
=
(Control)fc.Clone();
this
.Controls.Add(c);
}
}
我们用 “点击button1按钮” 来模拟 “从ToolBox中拖动Control到Form” 这个功能。这里仅仅实现了Label,我们还可以用同样的方法模拟Button,TreeView等控件。
案例2,调色板,这个案例参见
http://terrylee.cnblogs.com/archive/2006/01/16/317896.html
,其思想与案例1是一样的:每次得到的色笔都是一个copy,仅仅是颜色的不同。由于每种颜色由RGB三原色组合搭配而成,所以会有256^3个对象,为此,使用原型模式可以将这个对象减少为1个,可以看成是水彩画中的一支毛笔和RGB三个色盒。
原型模式可以解决抽象工厂平行子类太多的问题,同样的,Flyweight也可以实现,只是后者更倾向于结构而不关心生成,这时候要使用注册工厂。
对于DataSet ds:
ds.Copy()方法,返回ds的结构和数据;
ds.Clone()方法,返回ds的结构
原型模式的缺点:
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
关于深浅复制的定义:
浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式,所以如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个深拷贝的话,我们将创建一个新的对象和一个新的字符串--新对象将引用新字符串。需要注意的是执行深拷贝后,原来的对象和新创建的对象不会共享任何东西;改变一个对象对另外一个对象没有任何影响。
——以上摘自CLR框架设计,Array是最好的例证。
posted @ 2007-04-16 23:17
包建强
阅读(124)
评论(0)
编辑
收藏
所属分类:
Design Patterns
社区
新闻
新用户注册
刷新评论列表
标题
姓名
主页
Email
(只有博主才能看到)
验证码
*
看不清,换一张
[
登录
][
注册
]
内容(请不要发表任何与政治相关的内容)
Remember Me?
登录
使用高级评论
新用户注册
返回页首
恢复上次提交
[使用Ctrl+Enter键可以直接提交]
该文被作者在 2007-10-26 15:47 编辑过
所属分类的其他文章:
·
被遗忘的设计模式——1.不变模式(Immutable)
·
一些被遗忘的设计模式
·
我也设计模式——22.Iterator
·
我也设计模式——19.Mediator
·
我也设计模式——15.Chain of Responsablity
·
我也设计模式——9.Bridge
·
我也设计模式——16.Interpreter
·
我也设计模式——24.Template Method
·
我也设计模式——23.Strategy
·
我也设计模式——17.State
最新IT新闻:
·
第一财经周刊:当前互联网世界正处无秩序时代
·
Visual Studio 2008 SDK 1.1 发布
·
死敌VMware变身微软认证计划新成员
·
英特尔雅虎开发网络计算机频道
·
Windows Live视频邮件9月9日开始测试
博客园新闻频道
博客园首页
社区
公告
姓名:包建强
位置:中国 上海
学历:复旦大学数学系 本科
工作:某外企医疗研发中心 软件工程师
MSN:bjq_ren@hotmail.com
MVP:2008.7——2009.7
MVP配置
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
最新评论
我的标签
我管理的小组
读书(Books)
写书译书小组
博客园精华集出版小组
随笔分类
.NET C#(6)
(rss)
.NET CLR(24)
(rss)
.NET MSIL(21)
(rss)
.NET Reflection(6)
(rss)
.NET Serializable(6)
(rss)
.NET好书逐个评(2)
(rss)
AJAX(3)
(rss)
ASP.NET 2.0(14)
(rss)
Data Structures(2)
(rss)
Design Patterns(29)
(rss)
Open SourceCode(4)
(rss)
Others(49)
(rss)
SharpDevelop 0.92(11)
(rss)
T-SQL(2)
(rss)
WCF(2)
(rss)
WF(5)
(rss)
WPF(106)
(rss)
包包版网络棋牌大厅(9)
(rss)
博客园精花集(19)
(rss)
最新随笔
1. 包包版网络游戏大厅+桥牌系统 4.终于可以聊天了
2. 包包版网络游戏大厅+桥牌系统 目录 更新到第4章
3. (翻译)《Expert .NET 2.0 IL Assembler》 第三章 使代码更简单 3.4 小结
4. (翻译)《Expert .NET 2.0 IL Assembler》 第三章 使代码更简单
5. (翻译)《Expert .NET 2.0 IL Assembler》 第二章 代码加强 2.2 代码保护
6. (翻译)《Expert .NET 2.0 IL Assembler》 第二章 代码加强 2.3 小结
7. (翻译)《Expert .NET 2.0 IL Assembler》 第二章 代码加强 2.1 代码压缩
8. (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.3 类的预先声明
9. (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.4 小结
10. (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(三)
积分与排名
积分 - 153619
排名 - 229
最新评论
1. re: 有感于《博客园精华集》的原定方案不了了之,我很心痛,呼吁编委会对此举进行民主投票!
nnd,最讨厌这样利益熏心的出版社.................. (Martin(高超))
2. re: WPF笔记(2.7 文字布局)——Layout
请教,TextFlow在哪个xml命名空间中?我无法直接在VS2008的默认的WPF应用程序模板创建的项目中使用它。 (斯克迪亚)
3. re: WPF SDK研究 之 Layout布局
确实大家风范 (斯克迪亚)
4. re: 从分析Main函数开始
分析的源码版本低了吧,2.1版本和上面的完全不同 (cl250)
5. re: 博客园T恤窈窕女生版(附图)
就白色吗? (aierong)
6. re: 一些被遗忘的设计模式
看了不变模式,非常不错啊。
什么时候更新下面的模式啊。 (Colin Han)
7. re: (翻译)《Expert .NET 2.0 IL Assembler》 详要目录 更新到第3章
欢迎回来.. :) (dicky)
8. re: 包包版网络游戏大厅+桥牌系统 目录 更新到第4章
呵呵。。。
终于又回来了
太好了 (匿名)
9. re: WPF SDK研究 之 Layout布局
牛人也! (liang.li2009)
10. re: WPF SDK研究 之 数据绑定
good! (liang.li2009)