C#设计模式之4-原型模式
原型模式(Prototype Pattern)
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/395 访问。
原型模式属于创建型模式,使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
原型模式关注的是大量相同或相似对象的创建问题。应用原型模式就是建立一个原型,然后通过对原型来进行复制的方法,产生一个和原型相同或相似的新对象。
角色:
1、抽象原型(Prototype)
声明一个克隆自身的接口,通常名为Clone;
2、具体原型(Concrete Prototype)
实现一个克隆自身的操作,包含深拷贝和浅拷贝。
浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制,它们只是指向同一个引用。
深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制,它们拥有不同的副本。
注:C#中的MemberwiseClone属于浅克隆。
示例:
命名空间PrototypePattern包含细胞基类Cell,它的2个实现类分别为:PlantCell植物细胞类和Animal动物细胞类,另外包含CloneBase泛型基类。本案例尝试模拟细胞的分裂过程以展示原型模式在复制对象本身方面的独到之处。
namespace PrototypePattern
[Serializable]
public abstract class Cell : CloneBase<Cell> {
public int Id { get; set; }
public string Wall { get; set; }//细胞壁
public string Membrane { get; set; }//细胞膜
public string Cytoplasm { get; set; }//细胞质
public string Nucleus { get; set; }//细胞核
public Content Content { get; set; } = new Content();//细胞器
public Cell(int id,
string wall,
string membrane,
string cytoplasm,
string nucleus) {
this.Id = id;
this.Wall = wall;
this.Membrane = membrane;
this.Cytoplasm = cytoplasm;
this.Nucleus = nucleus;
this.Content = new Content();
}
public abstract Cell Division();
}
抽象细胞基类Cell,继承自CloneBase并定义Division分裂接口。
[Serializable]
public class PlantCell : Cell {
public PlantCell(int id,
string wall,
string membrane,
string cytoplasm,
string nucleus)
: base(id, wall, membrane, cytoplasm, nucleus) {
}
public override Cell Division() {
var cell = this.MemberwiseClone() as Cell;
cell.Id = RandomUtil.RandomNum();
return cell;
}
}
植物细胞类PlantCell,细胞基类的具体实现类,标记Serializable特性以支持序列化的深克隆。
[Serializable]
public class AnimalCell : Cell {
public AnimalCell(int id,
string wall,
string membrane,
string cytoplasm,
string nucleus)
: base(id, wall, membrane, cytoplasm, nucleus) {
}
public override Cell Division() {
var cell = this.MemberwiseClone() as Cell;
cell.Id = RandomUtil.RandomNum();
return cell;
}
}
动物细胞类AnimalCell,细胞基类的具体实现类,标记Serializable特性以支持序列化的深克隆。
[Serializable]
public class Content {
public string Mitochondria { get; set; }//线粒体
public int Chloroplasts { get; set; }//叶绿体
public int EndoplasmicReticulum { get; set; }//内质网
public int GolgiBody { get; set; }//高尔基复合体
public int Ribosomes { get; set; }//核糖体
public int Centrosome { get; set; }//中心体
public int Vacuole { get; set; }//液泡
public int Lysosomes { get; set; }//溶酶体
public int Microtubule { get; set; }//微管
}
细胞质类Content,为细胞基类中所包含的一个对象成员。
[Serializable]
public class CloneBase<T> {
public virtual T Clone() {
var memoryStream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, this);
memoryStream.Position = 0;
return (T)formatter.Deserialize(memoryStream);
}
}
克隆类CloneBase,包含一个虚拟的Clone方法以支持深克隆。
public class RandomUtil {
public static int RandomNum() {
return new Random().Next(1000000, 10000000);
}
}
产生细胞Id的工具类,从100万到1000万。
public class Program {
private static Cell _cell = null;
private const string SPLIT_BREAK =
"-----------------------------------------------------";
public static void Main(string[] args) {
_cell = new PlantCell(RandomUtil.RandomNum(),
"wall",
"membrane",
"cytoplasm",
"nucleus");
var plant = _cell.Division();
Console.WriteLine($"_cell.GUID:{_cell.Id},{Environment.NewLine}plant.GUID:{plant.Id}," +
$"{Environment.NewLine}equals:{_cell.Id == plant.Id}.");
Console.WriteLine(SPLIT_BREAK);
_cell.Content.Mitochondria = "10010101010100101010101";
Console.WriteLine($"_cell.Content.Mitochondria:{_cell.Content.Mitochondria},\r\n" +
$"plant.Content.Mitochondria:{plant.Content.Mitochondria}," +
$"{Environment.NewLine}equals:" +
$"{_cell.Content.Mitochondria == plant.Content.Mitochondria}.");
Console.WriteLine(SPLIT_BREAK);
var animal = _cell.Clone();
Console.WriteLine($"_cell.GUID:{_cell.Id},{Environment.NewLine}animal.GUID:{animal.Id}," +
$"{Environment.NewLine}equals:{_cell.Id == animal.Id}.");
Console.WriteLine(SPLIT_BREAK);
_cell.Content.Mitochondria = "01001010010100101010010";
Console.WriteLine($"_cell.Content.Mitochondria:{_cell.Content.Mitochondria},\r\n" +
$"animal.Content.Mitochondria:{animal.Content.Mitochondria}," +
$"{Environment.NewLine}equals:" +
$"{_cell.Content.Mitochondria == animal.Content.Mitochondria}.");
Console.WriteLine(SPLIT_BREAK);
Console.ReadKey();
}
}
以上是调用方的代码,植物细胞实例调用了浅克隆,而动物细胞实例调用了深克隆,请仔细分析这段代码。以下是这个案例的输出结果:
_cell.GUID:6768270,
plant.GUID:2028096,
equals:False.
-----------------------------------------------------
_cell.Content.Mitochondria:10010101010100101010101,
plant.Content.Mitochondria:10010101010100101010101,
equals:True.
-----------------------------------------------------
_cell.GUID:6768270,
animal.GUID:6768270,
equals:True.
-----------------------------------------------------
_cell.Content.Mitochondria:01001010010100101010010,
animal.Content.Mitochondria:10010101010100101010101,
equals:False.
-----------------------------------------------------
优点:
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/395 访问。
1、原型模式向客户隐藏了创建新实例的复杂性;
2、原型模式允许动态增加或较少产品类;
3、原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样;
4、产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构。
缺点:
1、每个类必须配备一个克隆方法或继承自CloneBase泛型类;
2、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
使用场景:
1、 当一个系统应该独立于它的产品创建、构成和表示时;
2、当要实例化的类是在运行时刻指定时,例如通过动态装载来创建一个类;
3、为了避免创建一个与产品类层次平行的工厂类层次时;
4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并Clone它们可能比每次用合适的状态手工实例化该类更方便一些。
C#设计模式之4-原型模式的更多相关文章
- 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:/ ...
- C#设计模式系列:原型模式(Prototype)
1.原型模式简介 1.1>.定义 原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 1.2>.使用频率 中 1.3>.原型模式应用 首先 ...
随机推荐
- There are unfinished transactions remaining. Please run yum-complete-transaction as root.
问题:CentOS 运行软件更新时,提示如下错误. 解决办法: 在终端界面,运行 sudo yum-complete-transaction.
- 地图热点 jquery.image-maps.js 的使用
在我悠闲了几天之后,我们后端给了我个任务,地图热点问题.简单来说,就是后台划出热点区域,设置链接,前端拿到数据渲染页面,显示热点区域.我主要使用了jquery.image-maps.js,并且添加了一 ...
- 自已动手作图搞清楚AVL树
@ 目录 一.背景 二.平衡二分搜索树---AVL树 2.1 AVL树的基本概念 结点 高度 平衡因子 2.2 AVL树的验证 三.旋转操作 3.1 L L--需要通过右旋操作 3.2 R R--需要 ...
- 性能测试必备知识(6)- 如何查看“CPU 上下文切换”
做性能测试的必备知识系列,可以看下面链接的文章哦 https://www.cnblogs.com/poloyy/category/1806772.html 课前准备,安装 sysbench 下载 sy ...
- APP自动化 -- 获取driver
一.appium设置 1.打开appium 2.设置 appium服务器:点击 高级设置 3.启动 appium 服务器 二.查看 .apk 安装包的“包名”和“活动入口名” 1.先复制本地 ...
- web自动化 -- HTMLreport(三)测试报告输出log日志
一.需求痛点 1.HTMLreport没法看到log日志,经过封装的框架不可能走一步就print() 2. 希望可以在HTMLreport中输出log日志 3.痛点截图 二.解决办法 1.既然是HTM ...
- web自动化 -- Keys(键盘操作)
Keys没啥好讲的 语法:Keys.CONTRAL 等等类似. 下方就是可以 Keys. 跟的键 那些 \ue000 就是对应的 Windows系统中的键盘码,pywin32 也一样的 ...
- 如何消灭飞机的“黑色十分钟”,AI来帮忙
近年来,“AI的应用和落地”逐渐成了具化的关键词,它和很多事物很多行业结合在一起,形成了奇妙的“化学反应”.例如,在日常生活中,AI可以推送我们喜欢的新闻或视频,可以在拍照的时候识别场景提升照片的美感 ...
- Redis一站式管理平台工具,支持集群创建,管理,监控,报警
简介 Redis Manager 是 Redis 一站式管理平台,支持集群的创建.管理.监控和报警. 集群创建:包含了三种方式 Docker.Machine.Humpback: 集群管理:支持节点扩容 ...
- Python Tuple(元组) len()方法
描述 Python 元组 len() 函数计算元组元素个数.高佣联盟 www.cgewang.com 语法 len()方法语法: len(tuple) 参数 tuple -- 要计算的元组. 返回值 ...