
原型模式
发布日期:2021-05-20 00:21:59
浏览次数:25
分类:精选文章
本文共 3398 字,大约阅读时间需要 11 分钟。
原型模式(Prototype Pattern)是一种软件设计模式,通过使用原型实例来指定创建对象的种类,并通过拷贝这些原型创建新的对象,从而避免重复代码的冗余。这一模式在开发中广泛应用,尤其在需要灵活对象创建的情况下。
什么是原型模式?
原型模式的核心思想是定义一个接口(通常称为原型接口),然后通过复制现有的实例并根据需要进行修改来创建新的实例。这使得系统能够在运行时灵活配置和创建对象,而无需公开构造函数或手动进行复杂的初始化操作。
为什么要使用原型模式?
在面对新对象的创建需求时,直接使用 new 运算符可能导致代码冗余,难以管理对象的创建逻辑。而原型模式通过复制现有对象实例来创建新对象,既提高了效率,又简化了代码结构。
原型模式的适用场景
原型模式适用于以下场景:
- 当系统需要独立于具体对象的构造过程管理时。
- 当需要在运行时客户端动态决定对象的具体实现方式时。
- 当需要避免在类层次中引入工厂类来管理对象的创建时。
- 当对象的状态在多个可能组合中时,通过预先定义原型来优化性能。
原型模式的优缺点
优点:
- 提供与构造函数 decoupling 的性能优势。
- 适用于大量对象的创建,其复杂性较低。
缺点:
- 必须实现 Cloneable 接口,增加了程序的复杂度。
- 当对象需要深度复制时,实现起来相对繁琐。
原型模式的分类
原型模式可以根据对象的复制方式划分为两种类型:
- 值类型的原型模式:采用 MemberwiseClone 方法实现浅复制,适用于对象内部所有成员变量都为值类型的情况。
- 引用类型的原型模式:需要自定义克隆方法实现深复制,确保新对象复制所有引用成员变量的引用。例如,使用 C# 的 Object.MemberwiseClone 方法实现浅复制,或者自定义克隆逻辑进行深复制。
具体案例:水果布丁制作
在实际开发中,原型模式可以用于创建对象的多种状态。例如,制作水果布丁时,不同的口味可能需要不同的材料组合。通过使用原型模式,可以预先定义各种原型,并通过复制这些原型来创建新的布丁实例。
值类型的原型模式示例
假设我们有一个 Pudding
类,它实现了 ICloneable
接口:
class Pudding : ICloneable{ private string name; // 水果布丁的名字 private int milk; // 牛奶 private int egg; // 鸡蛋 private int unsaltedbutter; // 淡奶油 private int sugar; // 糖 private string fruit; // 水果 public Pudding(string name) { this.name = name; } public void SetBasicMaterials(int milk, int egg, int unsaltedbutter) { this.milk = milk; this.egg = egg; this.unsaltedbutter = unsaltedbutter; } public void SetFlavorMaterials(int sugar, string fruit) { this.sugar = sugar; this.fruit = fruit; } public object Clone() { return (object)this.MemberwiseClone(); }}
在客户端代码中:
Pudding p1 = new Pudding("香蕉布丁");p1.SetBasicMaterials(250, 2, 60);p1.SetFlavorMaterials(30, "香蕉丁");Pudding p2 = (Pudding)p1.Clone();p2.SetFlavorMaterials(40, "香蕉丁");Pudding p3 = (Pudding)p1.Clone();p3.SetFlavorMaterials(45, "香蕉丁加苹果丁");p1.Show();p2.Show();p3.Show();Console.ReadKey();
这样,原始对象 p1
不会受到 p2
和 p3
修改的影响,每个对象都有正确的独立状态。
引用类型的原型模式示例
在引用类型的示例中,我们可以看到更复杂的对象结构。例如,Flavormaterials
类作为一个独立的对象,采用引用类型的原型模式,通过复制实现深复制:
public class Flavormaterials : ICloneable{ private int sugar; private string fruit; public int Sugar { get { return sugar; } set { sugar = value; } } public string Fruit { get { return fruit; } set { fruit = value; } } public object Clone() { return (object)MemberwiseClone(); }}
在 Pudding
类中:
class Pudding : ICloneable{ private string name; private int milk; private int egg; private int unsaltedbutter; private Flavormaterials _flavorMaterial = new Flavormaterials(); public Pudding(string name) { this.name = name; } public void SetFlavorMaterials(int sugar, string fruit) { _flavorMaterial.Sugar = sugar; _flavorMaterial.Fruit = fruit; } public object Clone() { Pudding copy = new Pudding(this.name); copy.milk = this.milk; copy.egg = this.egg; copy.unsaltedbutter = this.unsaltedbutter; return copy; }}
在客户端代码中:
Pudding p1 = new Pudding("香蕉布丁");p1.SetBasicMaterials(250, 2, 60);p1.SetFlavorMaterials(30, "香蕉丁");Pudding p2 = (Pudding)p1.Clone();p2.SetFlavorMaterials(40, "香蕉丁");Pudding p3 = (Pudding)p1.Clone();p3.SetFlavorMaterials(45, "香蕉丁加苹果丁");p1.Show();p2.Show();p3.Show();Console.ReadKey();
这里,p2
和 p3
分别复制了 p1
的基本属性和口味属性,显示的结果也说明了深复制的优势。
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月30日 22时20分43秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
CentOS 7.X 系统安装及优化
2023-01-26
Centos 7下安装php+mysql+nginx+wordpress教程新版
2023-01-26
CentOS 7之Postfix部署系列 (一) CentOS安装
2023-01-26
flask框架面向移动端的虚拟物品订购平台毕设源码+论文
2023-01-26
flask框架飞机订票管理系统(毕设源码+论文)
2023-01-26
flask框架餐饮管理系统毕设源码+论文
2023-01-26
flask框架高校助学及勤工俭学管理系统(毕设源码+论文)
2023-01-26
flask框架高校图书管理系统设计与实现(毕设源码+论文)
2023-01-26
flask框架高校招生预报管理系统(毕设源码+论文)
2023-01-26
flask框架高校教师个人数字档案(毕设源码+论文)
2023-01-26
flask框架高校毕业生选题系统(毕设源码+论文)
2023-01-26
flask框架高校竞赛信息管理系统(毕设源码+论文)
2023-01-26
flask框架魔方教学网站毕设源码+论文
2023-01-26
Flask解决跨域访问问题(Access to XMLHttpRequest at ‘http://127.0.0.1:500been blocked by CORS policy: No ‘Acc)
2023-01-26
Flatterer: 快速JSON转换工具使用指南
2023-01-26
Flex / PHP Security Basics - Part One
2023-01-26
FLEX 4 :选择本地文件编辑
2023-01-26
Flex 与 spring mvc 整合 BlazeDB
2023-01-26
flex 动态创建组件之容器自适应大小
2023-01-26