- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C#编程中使用设计模式中的原型模式的实例讲解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
1、引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,然后如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适,然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使用new运算符去创建相同的类实例对象,此时我们一般思路就是想——只创建一个类实例对象,如果后面需要更多这样的实例,可以通过对原来对象拷贝一份来完成创建,这样在内存中不需要创建多个相同的类实例,从而减少内存的消耗和达到类实例的复用。 然而这个思路正是原型模式的实现方式。下面就具体介绍下设计模式中的原型设计模式.
2、原型模式的详细介绍 我们来看一个入学考试场景实例 。
基对象(一般为接口,抽象类):考试题(样卷) 。
原型模式的复职克隆:根据需要印刷考卷,这里的考卷都是复制考试题样卷 。
客户端:学生答卷,同一套试卷,学生做题不可能一模一样 。
类图:
接口:试卷样例代码 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
/// <summary>
/// 选答题
/// </summary>
public
class
SelectTest
{
private
string
other;
public
string
你老婆多大
{
get
{
return
this
.other;
}
set
{
this
.other = value;
}
}
}
/// <summary>
/// 面试题
/// </summary>
public
interface
Itest
{
Itest Clone();
string
知道设计模式吗
{
get
;
set
;
}
string
设计模式有几种
{
get
;
set
;
}
string
你知道那些
{
get
;
set
;
}
SelectTest 附加题
{
get
;
set
;
}
Test Test
{
get
;
set
;
}
Test Test1
{
get
;
set
;
}
}
|
。
复制克隆:复印机 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
/// <summary>
/// 继承Itest接口
/// </summary>
public
class
Test : Itest
{
private
string
one;
private
string
two;
private
string
three;
private
SelectTest other=
new
SelectTest();
public
string
知道设计模式吗
{
get
{
return
this
.one;
}
set
{
this
.one = value;
}
}
public
string
设计模式有几种
{
get
{
return
this
.two;
}
set
{
this
.two = value;
}
}
public
string
你知道那些
{
get
{
return
this
.three;
}
set
{
this
.three = value;
}
}
public
SelectTest 附加题
{
get
{
return
this
.other;
}
set
{
this
.other = value;
}
}
#region IColorDemo 成员
public
Itest Clone()
{
//克隆当前类
return
(Itest)
this
.MemberwiseClone();
}
#endregion
}
|
客户端,发卷做题 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static
void
Main()
{
//印刷试卷
Itest test =
new
Test();
//复制样本试卷
Itest test1 = test.Clone();
//考生1
test.设计模式有几种 =
"23"
;
test.附加题.你老婆多大 =
"18"
;
//考生2
test1.设计模式有几种 =
"24"
;
test1.附加题.你老婆多大 =
"20"
;
//显示考生答卷内容
Console.WriteLine(
"test设计模式有几种:"
+ test.设计模式有几种);
//23
Console.WriteLine(
"test附加题.你老婆多大:"
+ test.附加题.你老婆多大);
//20
Console.WriteLine(
"test1设计模式有几种:"
+ test1.设计模式有几种);
//24
Console.WriteLine(
"test1附加题.你老婆多大:"
+ test1.附加题.你老婆多大);
//20
Console.ReadKey();
}
|
注意:这里两个人答得不一样,为什么附加题中,老婆年龄都为20?
这里涉及到深拷贝,浅拷贝问题,值类型是放在栈上的,拷贝之后,会自会在站上重新add一个,而class属于引用类型,拷贝之后,栈上重新分配啦一个指针,可指针却指向同一个位置的资源。浅拷贝,只拷贝值类型,深拷贝,引用类型也拷贝复制.
解决方案:
1
2
3
4
5
6
7
8
9
10
|
public
Itest Clone()
{
//克隆当前类
Itest itst= (Itest)
this
.MemberwiseClone();
SelectTest st =
new
SelectTest();
st.你老婆多大 =
this
.other.你老婆多大;
itst.附加题 = st;
return
itst;
}
|
使用序列化解决 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/// <summary>
/// 选答题
/// </summary>
[Serializable]
public
class
SelectTest
{
private
string
other;
public
string
你老婆多大
{
get
{
return
this
.other;
}
set
{
this
.other = value;
}
}
}
/// <summary>
/// 面试题
/// </summary>
public
interface
Itest
{
Itest Clone();
string
知道设计模式吗
{
get
;
set
;
}
string
设计模式有几种
{
get
;
set
;
}
string
你知道那些
{
get
;
set
;
}
SelectTest 附加题
{
get
;
set
;
}
}
/// <summary>
/// 继承Itest接口
/// </summary>
public
class
Test : Itest
{
private
string
one;
private
string
two;
private
string
three;
private
SelectTest other=
new
SelectTest();
public
string
知道设计模式吗
{
get
{
return
this
.one;
}
set
{
this
.one = value;
}
}
public
string
设计模式有几种
{
get
{
return
this
.two;
}
set
{
this
.two = value;
}
}
public
string
你知道那些
{
get
{
return
this
.three;
}
set
{
this
.three = value;
}
}
public
SelectTest 附加题
{
get
{
return
this
.other;
}
set
{
this
.other = value;
}
}
public
Itest Clone()
{
SerializableHelper SerializableHelper =
new
原型模式.SerializableHelper();
string
target = SerializableHelper.Serializable(
this
);
return
SerializableHelper.Derializable<Itest>(target);
}
}
public
class
SerializableHelper
{
public
string
Serializable(
object
target)
{
using
(MemoryStream stream =
new
MemoryStream())
{
new
BinaryFormatter().Serialize(stream, target);
return
Convert.ToBase64String(stream.ToArray());
}
}
public
object
Derializable(
string
target)
{
byte
[] targetArray = Convert.FromBase64String(target);
using
(MemoryStream stream =
new
MemoryStream(targetArray))
{
return
new
BinaryFormatter().Deserialize(stream);
}
}
public
T Derializable<T>(
string
target)
{
return
(T)Derializable(target);
}
}
|
这就是对原型模式的运用。介绍完原型模式的实现代码之后,下面看下原型模式的类图,通过类图来理清原型模式实现中类之间的关系。具体类图如下:
。
3、原型模式的优缺点 。
原型模式的优点有:
原型模式向客户隐藏了创建新实例的复杂性 原型模式允许动态增加或较少产品类。 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构 。
原型模式的缺点有: 每个类必须配备一个克隆方法 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候.
4、.NET中原型模式的实现 在.NET中可以很容易地通过实现ICloneable接口(这个接口就是原型,提供克隆方法,相当于与上面代码中MonkeyKingPrototype抽象类)中Clone()方法来实现原型模式,如果我们想我们自定义的类具有克隆的功能,首先定义类继承与ICloneable接口并实现Clone方法。在.NET中实现了原型模式的类如下图所示(图中只截取了部分,可以用Reflector反编译工具进行查看):
最后此篇关于C#编程中使用设计模式中的原型模式的实例讲解的文章就讲到这里了,如果你想了解更多关于C#编程中使用设计模式中的原型模式的实例讲解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
.NET 框架:4.5.1 我在 Blend for visual studio 2015 中遇到一个奇怪的错误,我找不到它的来源。 如果我在 VS 中打开我的 WPF 解决方案,它会加载并运行良好。
我经常遇到这样的问题,与 Hierarchical RESTful URL design 非常相似 假设该服务仅提供用户上传文档。 POST, GET /accounts PUT, DELETE /a
在 Rails 应用程序中,我使用 devise 来管理我的用户,而我用来销毁 session 的链接不再有效。它正在工作,现在我添加了事件管理员,但没有。 我的链接是 :delete, :clas
我已经坚持了超过 24 小时,试图按照此处发布的其他解决方案进行操作,但我无法使其正常工作。我是 Rails 新手,需要帮助! 我想让我的/users/edit 页面正常工作,以便我可以简单地更改用户
Devise 在以下情况下不会使用户超时: 用户登录,关闭选项卡,然后在超时 + X 分钟内重新访问该 URL。用户仍处于登录状态。 如果选项卡已打开并且稍后刷新/单击,则超时可以正常工作。这意味着
我想使用这样的 slider 我希望该 slider 根据提供给它的值进行相应调整。到目前为止,我只能应用具有渐变效果的背景,但无法获得这种效果。请通过提供样式代码来帮助我。
您应该为每种方法创建一个请求/响应对象,还是应该为每个服务创建一个? 如果我在所有方法中使用它,我的服务请求对象中将只有 5 个不同的东西,因为我对几乎所有方法使用相同的输入。 响应对象将只有一个字典
我正在尝试在 REST 中对实体的附件进行建模。假设一个缺陷实体可以附加多个附件。每个附件都有描述和一些其他属性(上次修改时间、文件大小...)。附件本身是任何格式的文件(jpeg、doc ...)
我有以下表格: Blogs { BlogName } BlogPosts { BlogName, PostTitle } 博客文章同时建模一个实体和一个关系,根据 6nf(根据第三个宣言)这是无效的。
如果 A 类与 B、C 和 D 类中的每一个都有唯一的交互,那么交互的代码应该在 A 中还是在 B、C 和 D 中? 我正在编写一个小游戏,其中许多对象可以与其他对象进行独特的交互。例如,EMP点击
关于如何记住我与 Omniauth 一起工作似乎有些困惑。 根据这个wiki ,您需要在 OmniauthCallbacksController 中包含以下内容: remember_me(user)
设计问题: 使用 非线程安全 组件(集合,API,...)在/带有 多线程成分 ... 例子 : 组件 1 :多线程套接字服务器谁向消息处理程序发送消息... 组件 2 :非线程安全 消息处理程序 谁
我们目前正在设计一个 RESTful 应用程序。我们决定使用 XML 作为我们的基本表示。 我有以下关于在 XML 中设计/建模应用程序数据的问题。 在 XML 中进行数据建模的方法有哪些?从头开始然
我正在设计一个新的 XSD 来从业务合作伙伴那里获取积分信息。对于每笔交易,合作伙伴必须提供至少一种积分类型的积分值。我有以下几点:
设计支持多个版本的 API 的最佳方法是什么。我如何确保即使我的数据架构发生更改(微小更改),我的 api 的使用者也不会受到影响?任何引用架构、指南都非常有用。 最佳答案 Mark Nottingh
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
我想用 php 创建一个网站,其工作方式与 https://www.bitcoins.lc/ 相同。确实,就每个页面上具有相同布局但内容会随着您更改链接/页面而改变而言,我如何在 php 中使用lay
我有一个关于编写 Swing UI 的问题。如果我想制作一个带有某些选项的软件,例如在第一个框架上,我有三个按钮(新建、选项、退出)。 现在,如果用户单击新按钮,我想将框架中的整个内容更改为其他内容。
我正在尝试找出并学习将应用程序拥有的一堆Docker容器移至Kubernetes的模式和最佳实践。诸如Pod设计,服务,部署之类的东西。例如,我可以创建一个其中包含单个Web和应用程序容器的Pod,但
我是一名优秀的程序员,十分优秀!