原型模式——创建型模式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

思路:

马上又到找工作的时候了,当我们在准备一份份简历的时候有没有考虑过这样一个问题?

面对不同的工作岗位我们需要准备不同的求职简历,但是这样的几份不同的简历中还是有相当大的部分是相同的,我们如果每一份都从头开始重新制作,无疑是做了很多的无用功,浪费了很多时间。

那么,我们有没有办法不用重新new一个简历,只是对某一个原件进行适当的修改,就能实现这个功能呢?

别忘了,我们是程序员呀,程序员别的不一定行,Ctrl+C和Ctrl+V还是很溜的。复制下来对需要修改的部分进行修改不就行了?

但是同样别忘了,我们是程序员,如果这样一个问题用程序的思维来看,又会是什么样呢?

我们需要一个简历类,我们可以设置个人信息、工作经历,并且把它们显示出来。我们可以怎么写呢?

    class Program{static void Main(string[] args){Resume a;a = new Resume("张三");a.SetPersonalInfo("男", "22");a.SetWorkExperience("1998-2000", "XX公司");a.SetAimCompany("Google");Resume b =  new Resume("张三");b = a;a.Display();b.Display();b.SetAimCompany("IBM");a.Display();b.Display();Console.Read();}}class Resume  //简历{private string name;private string sex;private string age;private string timeArea;private string company;private string AimCompany;public Resume(string name){this.name = name;}//设置个人信息public void SetPersonalInfo(string sex, string age){this.sex = sex;this.age = age;}//设置工作经历public void SetWorkExperience(string timeArea, string company){this.timeArea = timeArea;this.company = company;}//设置个人信息public void SetAimCompany(string AimCompany){this.AimCompany = AimCompany;}//显示public void Display(){Console.WriteLine("尊敬的" + AimCompany + "公司领导,您好:");Console.WriteLine("{0} {1} {2}", name, sex, age);Console.WriteLine("工作经历:{0} {1}", timeArea, company);Console.WriteLine("");}}

那么由以上代码的运行结果我们可以看到,当我们改变b的工作经历的时候,a的工作经历同样改变了。这是什么原因呢?因为

b=a;

这行代码执行的结果是,将a指向b的内容,并没有给a分配内存空间。所以改变了b实际上改变了a指向的内容。即并没有实现克隆的效果。

事实上,对于C#而言,因为克隆的常用,它在System命名空间里提供了ICloneable接口,其中一个惟一的方法就是Clone,我们只需要实现这个接口就好了,而不用去写它的原型抽象类了。

    class Program{static void Main(string[] args){Resume a = new Resume("张三");a.SetPersonalInfo("男", "22");a.SetWorkExperience("1998-2000", "XX公司");a.SetAimCompany("Google");Resume b = (Resume)a.Clone() ;a.Display();b.Display();b.SetAimCompany("IBM");a.Display();b.Display();Console.Read();}}//简历class Resume :  ICloneable{private string name;private string sex;private string age;private string timeArea;private string company;private string AimCompany;public Resume(string name){this.name = name;}//设置个人信息public void SetPersonalInfo(string sex, string age){this.sex = sex;this.age = age;}//设置工作经历public void SetWorkExperience(string timeArea, string company){this.timeArea = timeArea;this.company = company;}//设置个人信息public void SetAimCompany(string AimCompany){this.AimCompany = AimCompany;}//显示public void Display(){Console.WriteLine("尊敬的" + AimCompany + "公司领导,您好:");Console.WriteLine("{0} {1} {2}", name, sex, age);Console.WriteLine("工作经历:{0} {1}", timeArea, company);Console.WriteLine("");}public Object Clone(){return this.MemberwiseClone();//浅复制}}

有运行结果我们可以看出,对b进行改变并不会改变a的结果,即实现了克隆的效果。

但需要注意的是,这里的克隆其实只是浅克隆。

值类型在克隆的时候是逐位复制,为深复制。而引用类型在复制时不复制引用的对象,只复制引用,为浅复制。而在C#中,string类型为特殊的引用类型,他可以被当做值类型进行深复制。所以在这里只是进行浅复制就可以达到效果。

但是一旦需要克隆类类型的变量的时候,不进行深复制是不行的。例如,我们的简历类中有设置身份证的方法,而在实际中我们一般会有一个身份证类,其间有身份证属性和设置身份证号的方法。这样就需要我们提供一个对这些引用类型实现深复制的方法。

    class Program{static void Main(string[] args){Resume a = new Resume("张三");a.SetPersonalInfo("男", "22");a.SetWorkExperience("1998-2000", "XX公司");a.SetAimCompany("Google");Resume b = (Resume)a.DeepClone();a.Display();b.Display();b.SetAimCompany("IBM");b.idinfo.IdNumber = 56789;a.Display();b.Display();Console.Read();}}public class IDInfo{public int IdNumber;public IDInfo(int IdNumber){this.IdNumber = IdNumber;}}//简历class Resume : ICloneable{private string name;private string sex;private string age;private string timeArea;private string company;private string AimCompany;public IDInfo idinfo;public Resume(string name){this.name = name;idinfo = new IDInfo(123456);}//设置个人信息public void SetPersonalInfo(string sex, string age){this.sex = sex;this.age = age;}//设置工作经历public void SetWorkExperience(string timeArea, string company){this.timeArea = timeArea;this.company = company;}//设置个人信息public void SetAimCompany(string AimCompany){this.AimCompany = AimCompany;}//显示public void Display(){Console.WriteLine("尊敬的" + AimCompany + "公司领导,您好:");Console.WriteLine("{0} {1} {2}", name, sex, age);Console.WriteLine("工作经历:{0} {1}", timeArea, company);Console.WriteLine("ID号码:"+idinfo.IdNumber.ToString());Console.WriteLine("");}public Object Clone(){return this.MemberwiseClone();}public Object DeepClone(){Resume rsm = (Resume)this.MemberwiseClone();rsm.idinfo = new IDInfo(this.idinfo.IdNumber);return rsm;}}

以上,就是原型模式的思路和方法。

UML图:

140154_0KYn_2725918.png

吐槽:

原型模式就是从一个对象在创建另外一个可定制的对象,而且不需知道任何创建的细节。

优点:

一般在初始化信息不发生变化的情况下,克隆是最好的办法,这既隐藏了对象创建的细节,又对性能是大大的提高。因为它不需要从新初始化对象,而是动态的获得对象运行时的状态。

原型模式允许动态增加或减少产品类。

原型模式具有给一个应用软件动态加载新功能的能力。

产品类不需要非得有任何事先确定的等级结构 。

缺点:

每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。

在实现深克隆时需要编写较为复杂的代码。

使用情景:

创建新对象成本较大(CPU,初始化)。

系统要保存对象的状态,对象状态变化很小。

当一个类的实例只有几个不同状态组合时,建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化更为方便。

 

本菜鸟的疑难杂症:

1、在C#中类类型是引用类型,所以复制时默认浅复制。而string是一种特殊的引用类型,在处理的时候底层会把它当做值类型处理。

2、浅复制表明,被复制的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来对象。要实现复制之后引用类型不指向同一个对象,就需要把复制的对象所引用的对象都复制一遍,即深复制。深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

转载于:https://my.oschina.net/CoderBleak/blog/677163

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何获取 ASP.NET Core 当前启动地址?

前言上次,我们介绍了配置ASP.NET Core启动地址的多种方法。那么,如何通过代码方式,获取启动后的地址?WebApplication.Urls 对象使用 WebApplication.Urls.Add 方法可以添加启动地址。那么,使用 WebApplication.Urls 应…

【CASS精品教程】CASS9.1查询功能大全(坐标、长度、面积、方位角)

文章目录 1. 查询指定点坐标2. 查询两点距离及方位3. 查询线长4. 查询实体面积CASS9.1中提供了查询指定点坐标、查询两点距离及方位、查询线长、查询实体面积等查询功能,如下图所示: 本文以动画演示的方式,对以上提到的功能进行讲解。 1. 查询指定点坐标 点击【工程应用】…

自定义smokeping告警(邮件+短信)

前段时间接到公司IT同事需求,帮助其配置smokeping的告警功能,之前配置的姿势有些问题,告警有些问题,现在调试OK,在此将关键配置点简单记录下。 关键的配置项主要有: 定义告警规则并配置将告警信息通过管道交…

WPF 实现抽屉菜单

分享一个WPF 实现抽屉菜单抽屉菜单作者:WPFDevelopersOrg原文链接:https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40;Visual Studio 2022;项目使用 MIT 开源许可协议;更多效果可以通过GitHub[1]|码云[2]…

selenium 定制启动 chrome 的选项

2019独角兽企业重金招聘Python工程师标准>>> selenium 定制启动 chrome 的选项 博客分类: java 搜索引擎,爬虫 使用 selenium 时,我们可能需要对 chrome 做一些特殊的设置,以完成我们期望的浏览器行为,比如…

平台级 SAAS 架构的基础:统一身份管理系统

业内在用户统一身份认证及授权管理领域,主要关注 4 个方面:集中账号管理(Account)、集中认证管理(Authentication)、集中授权管理(Authorization)和集中审计管理(Audit&a…

【ArcGIS Pro微课1000例】0017:ArcGIS Pro 2.8制作炫酷的ETOPO1全球DEM地图

ArcGIS Pro相对于ArcGIS,在制图方面做了很大的提升,做出的地图更加优美,本文讲解基于NOAA的ETOPO1数据全球DEM数据制作炫酷的全球DEM地图,先看效果再教学! 1. 效果展示 全球 澳大利亚大陆

Js中的for in

2019独角兽企业重金招聘Python工程师标准>>> 后台数据&#xff1a; List<Map<String, Object>> uTags query.selectAllList("velocity.userGetTags", map); 前端解析&#xff1a; for(var i in data.content){//由于这里是List[i](Map).IDc…

VMWare 安装 Linux

参考 &#xff1a; http://www.aboutyun.com/thread-6780-1-1.html 这的是很详细。赞一下 我这里就简化一下。 1 下载&#xff1a; VMWare : https://download3.vmware.com/software/wkst/file/VMware-workstation-full-10.0.0-1295980.exe ubuntu : http://www.aboutyun…

【ArcGIS Pro微课1000例】0018:ArcGIS Pro 2.8通过OLE DB与个人数据库建立连接案例

对于个人数据库,Access程序可以直接打开。本文讲解在ArcGIS Pro2.8中通过OLE DB与个人数据库MDB建立联系的方法与过程。 文章目录 1. 个人数据库准备2. OLE DB连接个人数据库1. 个人数据库准备 准备一个个人数据库,在上面右键→复制文件地址。 文件地址为:"C:\test.md…

JAVA生成并导出json文件

将一个list集合转换成json文件并导出&#xff1a; 数据集合&#xff1a;    List<Object> agencyList new ArrayList<Object>();Map<String, Object> agencyMap new HashMap<>();agencyMap.put("agencyName",agencyName);agencyMap.pu…

《ASP.NET Core 6框架揭秘》实例演示[02]:基于路由、MVC和gRPC的应用开发

ASP.NET Core可以视为一种底层框架&#xff0c;它为我们构建出了基于管道的请求处理模型&#xff0c;这个管道由一个服务器和多个中间件构成&#xff0c;而与路由相关的EndpointRoutingMiddleware和EndpointMiddleware是两个最为重要的中间件。MVC和gRPC开发框架就建立在路由基…

什么是 JWT -- JSON WEB TOKEN

什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7519).该token被设计为紧凑且安全的&#xff0c;特别适用于分布式站点的单点登录&#xff08;SSO&#xff09;场景。JWT的声明一般被用来在身份提供者和服务提…

Re-installation failed due to different application signatures.

问题&#xff1a; 在虚拟设备上运行程序时提示安装失败。 [2010-08-08 00:38:30 - myApp] Re-installation failed due to different application signatures. [2010-08-08 00:38:30 - myApp] You must perform a full uninstall of the application. WARNING: This will remo…

【ArcGIS微课1000例】0024:ArcGIS如何连接文件夹、设认工作目录、默认地理数据库、相对路径与绝对路径?

ArcGIS软件在初次安装完成或者为了工作的方便,通常需要连接到指定的文件夹、设置默认工作路径,默认地理数据库、相对路径与绝对路径等。 文章目录 1. 文件夹连接2. 默认工作目录3. 默认地理数据库4. 相对路径与绝对路径1. 文件夹连接 在初次安装完ArcGIS时,默认没有文件夹连…

shell 用环境变量的值修改properties文件

假设有如下属性文件 demo.properties user.nametest user.password123456 ............................... 需求&#xff1a;先需要通过shell 脚本将 user.name 和 user.password 的value值替换为实际需要的用户名和密码&#xff0c; 将可以通过如下方式实现&#xff1a; sed …

【Spring Cloud】Redis缓存接入监控、运维平台CacheCloud

CacheCloud CacheCloud提供一个Redis云管理平台&#xff1a;实现多种类型(Redis Standalone、Redis Sentinel、Redis Cluster)自动部署、解决Redis实例碎片化现象、提供完善统计、监控、运维功能、减少运维成本和误操作&#xff0c;提高机器的利用率&#xff0c;提供灵活的伸缩…

[Win10应用开发] 使用 Windows 推送服务 (WNS)

前言 Windows 推送服务&#xff08;WNS&#xff09;也是 Win10 通知机制中的一种&#xff0c;今天与大家一起学习一下有关WNS的相关知识。使用 Windows 推送服务的前提是你需要有一个微软开发者账号&#xff0c;这样才能得到一些合法的密钥信息用于与WNS服务器完成通讯操作。 …

Windows 11 新版 25158 推送!全新搜索框和图标、小组件动态内容和通知标记

面向 Dev 频道的 Windows 预览体验成员&#xff0c;微软现已推送 Windows 11 预览版 Build 25158。主要变化1.微软宣布为 Windows 11 搜索引入全新视觉体验&#xff0c;由搜索框或重新设计的搜索图标呈现。目前该功能仅向部分 Windows 预览体验成员推出&#xff0c;将在未来向所…

Python之路【第一篇】:环境搭建

虚拟机安装 下载VMwareWorkstation以及centos,安装完VMwareWorkstation&#xff0c;创建一个虚拟机&#xff0c;然后在新创建的虚拟机上运行centos linux环境搭建 公司开发使用linux的原因&#xff1a;稳定、安全、开源 在虚拟机中使用centos这个版本&#xff0c;作为服务器端的…