设计模式之原型模式(Prototype)
1、出现原因
在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象” ,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?
2、意图:
使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。(将相同的部分进行赋值拷贝,不同的部分需要客户端自己决定)
3、结构图

4、代码演示
举例:比如楼房的基本信息是相同的,但是他们的门牌号码是不同的,需要客户自己决定的。
//原型接口
public interface IBuildingPrototype
{
string BuildingName { set; get; }
string BuildingNo { set; get; }
IBuildingPrototype Clone();
}
//实现原型接口的类
public class Building : IBuildingPrototype
{
public string BuildingName
{
get;
set;
} public string BuildingNo
{
get;
set;
} public IBuildingPrototype Clone()
{
Building building = new Building();
building.BuildingName = this.BuildingName;
return building;
}
}
实现Prototype模式的代码
客户端调用代码:
Building b1 = new Building();
b1.BuildingName = "小别墅";
b1.BuildingNo = "B1203";
IBuildingPrototype b2 = b1.Clone();
b2.BuildingNo = "B1230";
Console.WriteLine(b2.BuildingName+":"+b2.BuildingNo);
使用.Net内部的原型模式的ICloneable接口实现版本
public class BuildingIclone : ICloneable
{
public string BuildingName { set; get; }
public string BildingNo { get; set; }
public object Clone()
{
BuildingIclone building = new BuildingIclone();
building.BuildingName = this.BuildingName;
return building;
}
}
5、深拷贝和浅拷贝
提到拷贝:就要想到深拷贝和浅拷贝,下面就来讲解他们之间的区别:
他们之间的区别是体现在他们之中的 引用类型的 属性的 拷贝方式,其他值类型和string类型的属性只是直接拷贝数值:
浅拷贝:只是拷贝 引用类型的引用指针,新拷贝出来的实例的此属性还是指向原来的实例的属性的“地址”。
深拷贝:是将引用类型的属性 从新在内存中 创建一份 然后赋值给新拷贝到实例对应的属性。
在.Net中实现浅拷贝的方式Object.MemberwiseClone();
实现深拷贝要自己写代码了,实现的方式有两种:1)将浅拷贝来的实例的引用类型的属性在从新赋值一个新的从内存中创建的实例。
2)使用序列化的方式实现深拷贝(将浅拷贝的实例进行序列化,然后再反序列化得到深拷贝的实例)
代码来演示:
//下面演示 :浅拷贝和深拷贝的区别
[Serializable]
public class WorkExperience : ICloneable
{
public string CompanyName { get; set; } public int Time { get; set; } public object Clone()
{
return this.MemberwiseClone();
} public override string ToString()
{
return string.Format("在{0}公司工作了{1}年",CompanyName,Time);
}
} [Serializable]
public class Worker : ICloneable
{
public string Name { get; set; } public int Age { get; set; } public WorkExperience WorkExprien { set; get; } //浅拷贝
public Worker QianClone()
{
return (Worker)this.MemberwiseClone();
} //深拷贝(将浅拷贝的实例的引用类型属性从新赋值的方式)
public object Clone()
{
Worker worker = (Worker)this.MemberwiseClone();
worker.WorkExprien = (WorkExperience)this.WorkExprien.Clone();
return worker;
} //深拷贝(序列化版本),要将要被序列化的类打上Serializable的特性
public Worker ShenClone()
{
Worker worker = (Worker) this.MemberwiseClone();
BinaryFormatter binary = new BinaryFormatter();
using (Stream stream = new MemoryStream())
{
binary.Serialize(stream, this);
stream.Position = ;//将当前流 重新定位,,否则会报错:“在分析完成之前就遇到流结尾。”
return (Worker) binary.Deserialize(stream);
}
} }
深拷贝和浅拷贝
测试代码:
Worker worker = new Worker()
{
Name = "小明",
Age = ,
WorkExprien = new WorkExperience() { CompanyName="百度",Time=}
}; Worker w1 = worker.QianClone();//浅拷贝
Worker w2 = (Worker)worker.Clone();//深拷贝
Worker w3 = worker.ShenClone();//序列化版本的深拷贝
Console.WriteLine(worker.WorkExprien.Equals(w1.WorkExprien));//True
Console.WriteLine(worker.WorkExprien.Equals(w2.WorkExprien));//False
Console.WriteLine(worker.WorkExprien.Equals(w3.WorkExprien));//False
测试代码
6、.Net中的原型模式
1》就是上面提到的ICloneable接口
2》DataSet
Clone()方法:浅拷贝:只复制表的结构,不复制表的数据
Copy()方法:深拷贝:既复制表的结构,又复制表的数据
7、实现要点
1、产品的创建和初始化在类的Clone方法中完成
2、浅复制与深复制的区别
3、需要深复制的场合需要开发人员根据需要实现(在重写的 Clone 里 将引用类型 成员进行复制)
4、有些情况下Clone功能不容易实现,特别是遇到对象的循环引用时(例如:A关联B,同时B也关联A:就是A中有B,同时B中也有A。这样就会造成,A中的Clone克隆的时候,要将 B进行克隆,同时在 B的Clone里面进行 克隆的时候A也就被同时复制了,所以会一直循环复制下去)
8、效果
在运行时增加或删除产品:只要通过客户原型实例即可将新产品类型增加到系统中,例如组态软件中工具箱中的每个工具可以对应一个注册的原型对象,可以通过增加原形对象扩展工具箱。
很容易地创建复杂的对象:在图形编辑和组态等软件中,经常需要创建复杂的图元。这些图元是由简单图元组成的,采用原型模式可以很容易地将复杂图元作为一般图元来使用,使软件的工具箱具有自扩展功能
9、适用性:
1、当一个系统应该独立于产品的创建、构成和表示时,可以使用原型模式。
2、在使用时,我们可以用一些原型对象来代替生成相应对象的工厂对象,并且可以使拷贝、粘贴等操作独立于需要复制的对象。
10、总结
1、Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系(使用者不用关心,类内部的具体情况,直接复制就可以了),它同样要求这些“易变类”拥有“稳定的接口”。
2、Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新的对象(即原型)(只要已经创建一个就可以了),然后在任何需要的地方不断地Clone。
3、Prototype模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法(浅拷贝)或者序列化来实现深拷贝。
设计模式之原型模式(Prototype)的更多相关文章
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- [设计模式] 4 原型模式 prototype
设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...
- 设计模式 笔记 原型模式 prototype
//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...
- python 设计模式之原型模式 Prototype Pattern
#引入 例子1: 孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递下面是一个邮寄快递的场景:“给我寄个快递.”顾客说.“寄往什么地方?寄给……?”你问.“和上次差不多一样,只是邮 ...
- 【UE4 设计模式】原型模式 Prototype Pattern
概述 描述 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.如孙悟空猴毛分身.鸣人影之分身.剑光分化.无限剑制 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, ...
- 【设计模式】—— 原型模式Prototype
前言:[模式总览]——————————by xingoo 模式意图 由于有些时候,需要在运行时指定对象时哪个类的实例,此时用工厂模式就有些力不从心了.通过原型模式就可以通过拷贝函数clone一个原有的 ...
- 创建型设计模式之原型模式(Prototype)
结构 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 适用性 当要实例化的类是在运行时刻指定时,例如,通过动态装载:或者 为了避免创建一个与产品类层次平行的工厂类层次时:或 ...
- 设计模式五: 原型模式(Prototype)
简介 原型模式是属于创建型模式的一种,是通过拷贝原型对象来创建新的对象. 万能的Java超类Object提供了clone()方法来实现对象的拷贝. 可以在以下场景中使用原型模式: 构造函数创建对象成本 ...
- 设计模式之原型模式(prototype)
原理:拷贝自身对象实际上就是调用的拷贝构造函数,注意事项是这里的拷贝是深拷贝,即需要拷贝指针所指的内容 #include <stdio.h> #include <memory> ...
随机推荐
- CSS3中渐变gradient详解
这几天看了一本HTML5的书,里面对于页面的背景使用了大量的渐变效果,因此在这里写一些关于渐变Gradient的东西. CSS3中的Gradient有两种,分别是线性渐变(linear-gradien ...
- au3 命令
Case $Button1 _RunDOS(@SystemDir &"\sysdm.cpl");打开系统属性 ...
- iOS数据持久化-SQLite数据库使用详解
使用SQLite数据库 创建数据库 创建数据库过程需要3个步骤: 1.使用sqlite3_open函数打开数据库: 2.使用sqlite3_exec函数执行Create Table语句,创建数据库表: ...
- oledb 操作 excel
oledb excel http://wenku.baidu.com/search?word=oledb%20excel&ie=utf-8&lm=0&od=0 [Asp.net ...
- OC3-xml文件解析
<?xml version="1.0"?> <xml_api_reply version="1"> <cities> < ...
- (转)LR监控Linux系统性能计数器详解
从LR里面add measurement,填写linux机器的IP,出现所有unix/linux的计数器,包括cpu的,mem的,disk,network的.这里介绍几个常用的: (对于如何监控Lin ...
- Bring up a website by wordpress
WORDPRESS WordPress is web software you can use to create a beautiful website or blog, which is both ...
- Windows Phone 8.1开发:如何让ListView滚动到顶部,回到第一条?
Windows Phone 8.1开发中,ListView向下滑动了半天,用户如果突然想回头看看第一条数据怎么办? 如何让listView滚动到顶部,回到第一条? 很简单,一行代码.调用ListVie ...
- iOS屏幕尺寸和分辨率
iOS平台家族成员主要包括iPhone.iPod Touch和iPad,但是各类设备的分辨率各不相同,目前存在的尺寸主要有: iOS设备的尺寸多种多样,此外,屏幕的分辨率也有多种,总结如下表所示: 其 ...
- NSS_10 EXTJS给弹出的子窗口传递参数
在桌面程序中, 如果需要弹出一个子面板, 并且需要传一些参数给子面板, 我通常的作法就是:在子面板添加对应的数据成员,然后一个构造函数来接收这些参数并赋值级数据成员. 实现起来非常方便. 但是在Ext ...