设计模式(5)原型模式(Prototype)
设计模式(3)抽象工厂模式(Abstract Factory)
0 原型模式简介
0.0 原型模式定义
原型模式是一种常用的创建型模式,原型模式的一般定义为用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
原型模式要求对象必须具有一个可以“克隆”自身的方法,这样就可以通过这个克隆自身的方法创建一个新的同一类型的实例。我们通常将这个克隆自身的方法定义在抽象的接口上,直接通过接口调用其内部包含的克隆方法,创建一个具体的对象。这样就可以实现通过原型模式创建具体对象,无需关注这个对象本身的类型,也不用关心其内部的具体实现,而无须再去通过new去创建具体的类型的实例。
原型模式的结构图如下

Prototype:声明一个克隆自身的接口,用来约束想要克隆自身的类,所有想要实现克隆自身这一功能的类需要继承此接口,并且实现该接口里定义的克隆自身的方法
ConcretePrototype:实现了Prototype接口的具体实现类,这些类中负责Clone这一方法的具体实现
Client:客户端,通过原型实例克隆自身的Clone方法创建新的对象实例
0.1 原型模式应用场景
在war3中,有一个道具叫做“幻象权杖”其作用是使用后能制造目标单位的一个幻象。我们不考究幻象的其他具体细节,从外形上是与本体完全一摸一样的。
我们先创建一个英雄的接口
/// <summary>
/// 英雄接口定义
/// </summary>
public interface IHero
{
/// <summary>
/// 身体特征
/// </summary>
string Body { get; set; } /// <summary>
/// 武器
/// </summary>
string Weapon { get; set; } /// <summary>
/// 坐骑
/// </summary>
string Mount { get; set; }
}
DH类具体实现
/// <summary>
/// 恶魔猎手
/// </summary>
public class DH : IHero
{ /// <summary>
/// 身体特征
/// </summary>
public string Body
{
get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; }
set { }
} /// <summary>
/// 武器
/// </summary>
public string Weapon
{
get { return "艾辛诺斯双刃。"; }
set { }
} /// <summary>
/// 坐骑
/// </summary>
public string Mount
{
get { return "我有这双脚有这双腿。"; }
set { }
}
}
POM类具体实现
/// <summary>
/// 月亮女祭司
/// </summary>
public class POM : IHero
{
/// <summary>
/// 身体特征
/// </summary>
public string Body
{
get { return "夜幕只为朱颜改,群星陨落无穷。"; }
set { }
} /// <summary>
/// 武器
/// </summary>
public string Weapon
{
get { return "索利达尔·群星之怒。"; }
set { }
} /// <summary>
/// 坐骑
/// </summary>
public string Mount
{
get { return "艾斯卡达尔。"; }
set { }
}
}
幻象权杖类实现
/// <summary>
/// 幻象权杖
/// </summary>
public class WandOfIllusion
{
public static IHero Use(IHero hero)
{
IHero result = null;
if (hero is DH)
{
result = new DH();
}
else if (hero is POM)
{
result = new POM();
}
return result;
}
}
客户端使用
class Program
{
static void Main(string[] args)
{
DH dh = new DH();
var dh1 = WandOfIllusion.Use(dh); // 对dh使用幻象权杖
Console.ReadLine();
}
}
这样可以实现英雄使用幻象权杖复制自身这一基本需求,但是明显存在一下问题
1、通过幻象权杖复制英雄对象本身 这一通用的功能代码中,不应该强依赖具体的英雄类,应该是与具体的实现无关的。
2、难以扩展,要实现其他英雄使用幻象权杖这一操作,就必须修改幻象权杖类,里面需要增加更多的类型判断。而且我们这里只做了简要的对象创建处理,而实际中各个对象的创建过程是千差万别的,这样我们的幻象权杖类就会变得越来越难以维护。
基于问题的出现以及上述对原型模式的介绍,我们可以使用原型模式解决这一问题。
1 原型模式详解
0、英雄接口增加Clone方法
按照原型模式的要求,我们需要在英雄接口中增加一个Clone方法,所有英雄的具体实现类实现此方法,完成复制英雄的具体细节。
/// <summary>
/// 英雄接口定义
/// </summary>
public interface IHero
{
/// <summary>
/// 身体特征
/// </summary>
string Body { get; set; } /// <summary>
/// 武器
/// </summary>
string Weapon { get; set; } /// <summary>
/// 坐骑
/// </summary>
string Mount { get; set; } /// <summary>
/// Clone本身接口定义
/// </summary>
/// <returns></returns>
IHero Clone();
}
1、具体英雄实现类实现Clone方法
/// <summary>
/// 恶魔猎手
/// </summary>
public class DH : IHero
{ /// <summary>
/// 身体特征
/// </summary>
public string Body
{
get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; }
set { }
} /// <summary>
/// 武器
/// </summary>
public string Weapon
{
get { return "艾辛诺斯双刃。"; }
set { }
} /// <summary>
/// 坐骑
/// </summary>
public string Mount
{
get { return "我有这双脚有这双腿。"; }
set { }
} /// <summary>
/// Clone
/// </summary>
/// <returns></returns>
public IHero Clone()
{
IHero hero = new DH();
//TODO:进行其他Clone相关操作
return hero;
}
}
/// <summary>
/// 月亮女祭司
/// </summary>
public class POM : IHero
{
/// <summary>
/// 身体特征
/// </summary>
public string Body
{
get { return "夜幕只为朱颜改,群星陨落无穷。"; }
set { }
} /// <summary>
/// 武器
/// </summary>
public string Weapon
{
get { return "索利达尔·群星之怒。"; }
set { }
} /// <summary>
/// 坐骑
/// </summary>
public string Mount
{
get { return "艾斯卡达尔。"; }
set { }
} /// <summary>
/// Clone
/// </summary>
/// <returns></returns>
public IHero Clone()
{
IHero hero = new POM();
//TODO:进行其他Clone相关操作
return hero;
}
}
2、修改幻象权杖类
/// <summary>
/// 幻象权杖
/// </summary>
public class WandOfIllusion
{
public static IHero Use(IHero hero)
{
IHero result = null;
//if (hero is DH)
//{
// result = new DH();
//}
//else if (hero is POM)
//{
// result = new POM();
//}
result = hero.Clone();
return result;
}
}
至此我们的幻象权杖通用类,已经与具体的英雄实现类无关了。
3、浅克隆和深克隆
浅克隆:只克隆值类型的属性数据
深克隆:除了要复制浅克隆需要复制的值类型属性数据外,也要复制引用类型的属性数据。
2 总结
优点
对客户端调用隐藏具体实现类细节,减少外部调用对具体实现类的依赖
缺点
每个实现类都必须实现Clone方法,尤其在包含引用类型的深克隆时,需要逐级让所有的引用类型实现Clone
设计模式(5)原型模式(Prototype)的更多相关文章
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- [设计模式] 4 原型模式 prototype
设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...
- 设计模式 笔记 原型模式 prototype
//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...
- python 设计模式之原型模式 Prototype Pattern
#引入 例子1: 孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递下面是一个邮寄快递的场景:“给我寄个快递.”顾客说.“寄往什么地方?寄给……?”你问.“和上次差不多一样,只是邮 ...
- 【UE4 设计模式】原型模式 Prototype Pattern
概述 描述 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.如孙悟空猴毛分身.鸣人影之分身.剑光分化.无限剑制 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, ...
- 【设计模式】—— 原型模式Prototype
前言:[模式总览]——————————by xingoo 模式意图 由于有些时候,需要在运行时指定对象时哪个类的实例,此时用工厂模式就有些力不从心了.通过原型模式就可以通过拷贝函数clone一个原有的 ...
- 创建型设计模式之原型模式(Prototype)
结构 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 适用性 当要实例化的类是在运行时刻指定时,例如,通过动态装载:或者 为了避免创建一个与产品类层次平行的工厂类层次时:或 ...
- 设计模式五: 原型模式(Prototype)
简介 原型模式是属于创建型模式的一种,是通过拷贝原型对象来创建新的对象. 万能的Java超类Object提供了clone()方法来实现对象的拷贝. 可以在以下场景中使用原型模式: 构造函数创建对象成本 ...
- 设计模式之原型模式(prototype)
原理:拷贝自身对象实际上就是调用的拷贝构造函数,注意事项是这里的拷贝是深拷贝,即需要拷贝指针所指的内容 #include <stdio.h> #include <memory> ...
随机推荐
- JMeter 线程组之ConcurrencyThreadGroup介绍
线程组之ConcurrencyThreadGroup by:授客 QQ:1033553122 测试环境 apache-jmeter-3.2 jmeter-plugins-manager-1.3.jar ...
- Linux Linux下最大文件描述符设置
Linux下最大文件描述符设置 by:授客 QQ:1033553122 1. 系统可打开最大文件描述符设置 查看系统可打开最大文件描述符 # cat /proc/sys/fs/file-max 6 ...
- 小程序实践(一):主页tab选项实现
官方文档 效果图: 实现底部Tab选项,只需要在项目根目录下的app.json下修改 如图: ----------------------------------------------------- ...
- Android 逆向实战篇(加密数据包破解)
1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...
- Unity编译时找不到AndroidSDK的问题 | Unable to list target platforms(转载)
原文:http://www.jianshu.com/p/fe4c334ee9fe 现象 在用 Unity 编译 Android 平台的应用时,遇到 Unable to list target plat ...
- Android P的APP适配总结,让你快人一步
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由QQ音乐技术团队发表于云+社区专栏 上篇:Android P 行为变更适配 Android P 这次有很多行为变更,其中不乏一些需要亟 ...
- 微信小程序 刷新当前页面
刷新当前页面 Measure 法一: 需要的地方 this.onLoad(),试过之后,无用!!! 法二:亲测有效 在this.onReady()中进行获取数据操作(这样一来,就既可以在初次显示时直接 ...
- Flutter 布局(四)- Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth详解
本文主要介绍Flutter布局中的Baseline.FractionallySizedBox.IntrinsicHeight.IntrinsicWidth四种控件,详细介绍了其布局行为以及使用场景,并 ...
- JAVA基础库的使用点滴
Idea中双击SHIFT可以搜索[Eclipse中也有],这个很重要,可以找到当前的项目中可以引擎的已有的类,不要再次自己发明轮子 各种Util先在基础库和开源库中找 Base64编码 guava:c ...
- Unity网页游戏
Unity网页游戏是跑在浏览器的UnityWebPlayer插件中的,运行的模式是webplayer.unity3d+html 在嵌入UnityWebPlayer的网页中会调用UnityObject2 ...