设计模式(C#)——04原型模式
推荐阅读:
在软件开发过程中,我们习惯使用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原型模式的更多相关文章
- java23种设计模式——四、原型模式
源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...
- Net设计模式实例之原型模式( Prototype Pattern)
一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...
- Java设计模式5:原型模式
原型模式 原型模式属于对象的创建模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意. 原型模式结构 原型模式要求对象实现一个 ...
- 设计模式学习心得<原型模式 Prototype >
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现了一个原型接口,该接口用于创建当 ...
- IOS设计模式浅析之原型模式(Prototype)
原型模式的定义 “使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象”.最初的定义出现于<设计模式>(Addison-Wesley,1994). 简单来理解就是根据这个原型创建 ...
- 大话设计模式Python实现-原型模式
原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 一个原型模式的简单demo: #!/usr/bin/env python # -*- c ...
- 重学 Java 设计模式:实战原型模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老板你加钱我的代码能飞 程序员这份工作里有两种人:一类是热爱喜欢的.一类是仅当成工作 ...
- 深度分析:java设计模式中的原型模式,看完就没有说不懂的
前言 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的 ...
- 设计模式系列之原型模式(Prototype Pattern)——对象的克隆
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
随机推荐
- HttpWebRequest的使用之Get和Post的差别(C#)
这两天做的是通过一个HttpWebRequest将采集地址发送到服务端,服务端会返回一个JSON格式的字符串,然后我这边再对这个JSON进行反序列化,得到我想要的数据.在这篇文章里我简单介绍一下Htt ...
- python课堂整理17---文件操作(上)
1.在同一目录下新建文本文件 “爱了” 2.在该文件下写入内容,同时留意pycharm右下角的编码格式为 utf- 8 3.下面程序中的read函数会索引系统默认的编码格式,winx下是gbk ,所以 ...
- 【Demo 1】基于object_detection API的行人检测 3:模型训练并在OpenCV调用模型
训练准备 模型选择 选择ssd_mobilenet_v2_coco模型,下载地址(https://github.com/tensorflow/models/blob/master/research/o ...
- 【iOS】使用 CocoaPods 导入文件没有提示
解决方法: 选择工程的 TAEGETS -> Build Settings, 找到 Search Paths 下的 User Header Search Paths选项,如图所示: 点击 “+” ...
- JDBC连接池-C3P0连接
JDBC连接池-C3P0连接 c3p0连接池的学习英语好的看英文原版 c3p0 - JDBC3 Connection and Statement Pooling 使用c3p0连接池 三种方 ...
- 表单与v-model
基本用法 vue.js提供了v-model指令,用于在表单类元素上双向绑定数据,例如在输入框上使用,输入的内容会实时映射到绑定的数据上 example1:修改input框内容,message会实时渲染 ...
- LFS8.3BOOT引导疑点解决
LFS系统 的BOOT引导 在LFS书中写到的BOOT引导,时直接将宿主机的BOOT分区挂载当LFS的BOOT分区中,虽然这样也是可以实现BOOT引导的,但是我并不想这样做,所以BOOT引导就变得有些 ...
- Docker系列开篇之Virtual Machine VS Container(一)
前言 本节开始我们正式进入Docker系列,网上关于Docker相关文章如数家珍,写博客至今,我也一直在朝着如何写出通俗易懂且不枯燥的文章这个目标前进,喃喃自语的同时也希望看到文章的童鞋能明白我在讲什 ...
- 用HTML5的Audio标签做一个歌词同步的效果
HTML5出来这么久了,但是关于它里面的audio标签也就用过那么一次,当然还仅仅只是把这个标签插入到了页面中.这次呢就刚好趁着帮朋友做几个页面,拿这个audio标签来练练手. 首先你需要向页面中插入 ...
- Letters Shop
B. Letters Shop time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...