推荐阅读:

      在软件开发过程中,我们习惯使用new来创建对象。但是当我们创建一个实例的过程很昂贵或者很复杂,并且需要创建多个这样的类的实例时。如果仍然用new操作符去创建这样的类的实例,会导致内存中多分配一个一样的类实例对象,增加创建类的复杂度和消耗更多的内存空间。

      如果采用简单工厂模式来创建这样的系统。随着产品类增加,子类数量不断增加,会增加额外系统复杂程度,为此我们不得不引入原型模式了。

原型模式(Prototype Pattern)

      原型模式:创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

那么,我们如何用原型模型解决上面的问题呢?

      在原型模型中,因为每个类实例都是相同的,当我们需要多个相同的类实例时我们可以考虑只创建一个类实例对象,如果后面需要更多这样的实例,可以通过对原来对象拷贝一份来完成创建,这样在内存中不需要创建多个相同的类实例,从而减少内存的消耗和达到类实例的复用。

原型模式要素:

①抽象原型:声明一个克隆自身的接口;

②具体原型:该类继承了原型类,用来实现一个克隆自身的操作。

克隆操作分为:

浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制,它们只是指向同一个引用。

深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制,它们拥有不同的副本。

下面举个孙悟空复制猴子猴孙的例子来帮助大家理解原型模式:

      命名空间原型模式,包含孙悟空基类MonkeyKing,孙悟空就是原型模式中的原型对象;实现类创建猴子猴孙CreateMonkey,另外包含CloneBase泛型基类。

1创建孙悟空基类MonkeyKing


abstract class MonkeyKing
{
public abstract Prototype Clone();
}

2.创建悟空子类CreateMonkey


class CreateMonkey: MonkeyKing
{
private string monkey; //成员变量 public string monkey
{
get { return monkey; }
set { monkey= value; }
} //克隆方法
public override MonkeyKing Clone()
{
CreateMonkey monkeyKing= new CreateMonkey();
monkeyKing.monkey= monkey;
return monkeyKing;
}
}

3.使用原型模型

namespace 抽象工厂模式
{
class Program
{
static void Main(string[] args)
{
CreateMonkey createMonkey = new CreateMonkey();
CreateMonkey copy = (CreateMonkey)createMonkey.Clone();
Console.ReadLine();
}
}
}

      上面我们简单使用原型模式来实现孙悟空克隆猴子猴孙。由于前面我们讲到从具体原型的克隆方法分为浅克隆和深克隆,下面我将继续带领大家使用C#提供的MemberwiseClone()方法和ICloneable接口来实现浅克隆和深克隆。

一.浅克隆

1.创建抽象原型WorkExperience

	class WorkExperience : ICloneable
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}
public Object Clone()
{
return (object)this.MemberwiseClone();
}
}

2.创建具体原型

	class Resume : ICloneable
{
private string name;
private string sex;
private string age; private WorkExperience work; //引用工作对象经历
public Resume(string name)
{
this.name = name;
work = new WorkExperience(); //实例化 工作经历
} public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
} public void SetWorkExperience(string workDate, string company)
{
work.WorkDate = workDate;
work.Company = company;
} public void Display()
{
Console.WriteLine("{0},{1},{2}",name,sex,age);
Console.WriteLine("工作经历 {0},{1}",work.WorkDate,work.Company);
} public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}

3.使用原型

    class Program
{
static void Main(string[] args)
{
Resume a = new Resume("马云");
a.SetPersonalInfo("男", "40");
a.SetWorkExperience("2010--2018", "X公司"); Resume b = (Resume)a.Clone();
b.SetWorkExperience("2000--2010", "XX公司"); Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperience("1993--2000", "XXX公司"); a.Display();//xxx公司
b.Display();//xxx公司
c.Display();//xxx公司 Console.ReadKey();
}
}

二.深克隆

1.创建抽象原型WorkExperience

	class WorkExperience : ICloneable
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}
public Object Clone()
{
return (object)this.MemberwiseClone();
}
}

2.创建具体原型

	class Resume : ICloneable
{
private string name;
private string sex;
private string age; private WorkExperience work;
public Resume(string name)
{
this.name = name;
work = new WorkExperience();
}
private Resume(WorkExperience work) //克隆工作经历
{
this.work = (WorkExperience)work.Clone();
} public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
} public void SetWorkExperience(string workDate, string company)
{
work.WorkDate = workDate;
work.Company = company;
} public void Display()
{
Console.WriteLine("{0},{1},{2}",name,sex,age);
Console.WriteLine("工作经历 {0},{1}",work.WorkDate,work.Company);
} public Object Clone()
{
Resume obj = new Resume(this.work); 给关键字段去赋值
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age;
return obj;
}
}

3.使用原型

   class Program
{
static void Main(string[] args)
{
Resume a = new Resume("靖凡");
a.SetPersonalInfo("男", "29");
a.SetWorkExperience("2010--2018", "X公司"); Resume b = (Resume)a.Clone();
b.SetWorkExperience("2000--2010", "XX公司"); Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperience("1993--2000", "XXX公司"); a.Display();//x公司
b.Display();//xx公司
c.Display();//xxx公司 Console.ReadKey();
}
}

      通过上面三个例子,如果你对原型模式有了更好的理解,麻烦文末点个赞,如果你有什么疑惑,也欢迎评论区留言!!!

设计模式(C#)——04原型模式的更多相关文章

  1. java23种设计模式——四、原型模式

    源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...

  2. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  3. Java设计模式5:原型模式

    原型模式 原型模式属于对象的创建模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意. 原型模式结构 原型模式要求对象实现一个 ...

  4. 设计模式学习心得<原型模式 Prototype >

    原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现了一个原型接口,该接口用于创建当 ...

  5. IOS设计模式浅析之原型模式(Prototype)

    原型模式的定义 “使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象”.最初的定义出现于<设计模式>(Addison-Wesley,1994). 简单来理解就是根据这个原型创建 ...

  6. 大话设计模式Python实现-原型模式

    原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 一个原型模式的简单demo: #!/usr/bin/env python # -*- c ...

  7. 重学 Java 设计模式:实战原型模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老板你加钱我的代码能飞 程序员这份工作里有两种人:一类是热爱喜欢的.一类是仅当成工作 ...

  8. 深度分析:java设计模式中的原型模式,看完就没有说不懂的

    前言 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的 ...

  9. 设计模式系列之原型模式(Prototype Pattern)——对象的克隆

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

随机推荐

  1. C# 怎样将DateTime类型进行日期的加减

    C#中 DateTime类型有封装好的函数 例如: //将当前时间转换为指定格式的DateTime类型 DateTime dt=DateTime.Parse(DateTime.Now.ToString ...

  2. linux初学者-mail篇

     linux初学者-mail篇 邮件是在生活中比较常用的一个工具,在linux系统中的邮件也是.在linux中,邮件的发送所用的服务时postfix,邮件的接收所用的服务是pop(110端口).ima ...

  3. linux初学者-squid代理篇

     linux初学者-squid代理篇 Squid代理服务器是一种缓存服务器,一般分为正向代理和反向代理. 1.正向代理 客户端因为网络或者其他的问题,不能访问到一台Apache服务器,如果要访问到,则 ...

  4. Nginx 的简单使用 (IIS,Asp.Net)

    Nginx 的一些常见功能(windows,AspNet ,IIS) 下载 官方网站:https://nginx.org/en/download.html 下载,解压缩是这个样子 启动: 启动方式有两 ...

  5. Cordova-iOS SDK封装

    源码编译与制作静态库 下载cordova-ios源码,下载地址为:cordova-ios 解压后使用Xcode进行编译,编译选定模拟器和Generic iOS Device,cmd+B,编译成功(Dy ...

  6. 前端笔记之React(六)ES6的Set和Map&immutable和Ramda和lodash&redux-thunk

    一.ES6的Set.Map数据结构 Map.Set都是ES6新的数据结构,都是新的内置构造函数,也就是说typeof的结果,多了两个: Set 是不能重复的数组 Map 是可以任何东西当做键的对象 E ...

  7. 8天入门docker系列 —— 第八天 让程序跑在swarm集群上

    真正的落地部署都是希望程序跑在集群下,而不是单机版下测测玩玩,所以这篇就来聊一下怎么使用docker swarm进行部署,因为是swarm是docker自带的, 所以部署起来还是非常简单的. 一:前置 ...

  8. 详解 Diff 算法以及循环要加 key 值问题

    上一篇文章我简述了什么是 Virtual DOM,这一章我会详细讲 Diff 算法以及为什么在 React 和 Vue 中循环都需要 key 值. 什么是 DOM Diff 算法 Web 界面其实就是 ...

  9. Flink 从0到1学习—— 分享四本 Flink 国外的书和二十多篇 Paper 论文

    前言 之前也分享了不少自己的文章,但是对于 Flink 来说,还是有不少新入门的朋友,这里给大家分享点 Flink 相关的资料(国外数据 pdf 和流处理相关的 Paper),期望可以帮你更好的理解 ...

  10. Android 虹软人脸识别SDK-人脸对比

    准备 : 登录官方网站,获取SDK,进行个人验证后新建项目,获取APP_ID,和SDK_KEY: https://ai.arcsoft.com.cn/ucenter/resource/build/in ...