设计模式之原型模式(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> ...
随机推荐
- 适配i5,要加入i5的启动页才行,否则运行的效果还是i4
适配i5,要加入i5的启动页才行,否则运行的效果还是i4
- 【JS Note】字符串截取
Js中字符截取常用的三个函数:slice().substring().substr(). slice(): slice(start,[end]) 第一个参数代表开始位置,第二个参数代表结束位置的下一个 ...
- 跟我一起学习ASP.NET 4.5 MVC4.0(四)(转)
前几个文章中介绍了一些关于MVC4.0的东东,今天我们来看一下登陆验证,也可以说是权限验证,即AuthorizeAttribute.这个可以使用在控制器Controller上,也可以使用在Action ...
- C#常用的字符串操作, 包括截取
1.取字符串的前i个字符 (1)string str1=str.Substring(0,i); (2)string str1=str.Remove(i,str.Length-i); 2.去掉字符串的前 ...
- Java中Properties类的学习总结
学习目标: 1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 一.认识prope ...
- 使用命令修改ip地址
简述:以serverv 2012 r2为例 常用的几种,当然不全,希望能较快的速率记下一种便可 直接配置 1. 查看网卡的显示名称 2. 配置静态iP地址 3. 查看配置 ...
- iOS 最新版 CocoaPods 的安装使用
当在开发iOS应用时,会经常使用到很多的第三方开源类库,一般的方法是直接从GitHub下载,然后拖到项目中使用,如果该开源类库不依赖其他的类库,就可以直接使用:如果该开源类库还依赖一些其他的类库,则需 ...
- 【学习笔记】【C语言】指向结构体的指针
1.指向结构体的指针的定义 struct Student *p; 2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...
- MVC5 属性路由
属性路由(attribute routing)是最新被引进到MVC5中的,它和传统路由共同组成了mvc5中的两种主要路由. 1. 高质量的url应该满足以下几点 域名便于记忆和拼写 简短 便于输入 可 ...
- UI1_UITabBarController
// // AppDelegate.h // UI1_UITabBarController // // Created by zhangxueming on 15/7/8. // Copyright ...