一、动机(Motivation)

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

二、意图(Intent)

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象——《设计模式》GoF

三、结构(Structure)

我们看了这么多设计模式的类图了,大家应该也总结出一些经验来,客户端依赖的都是抽象的接口,【这个接口不是C#语言里面的Interface或者抽象类】,原型模式里面有一个抽象原型对象,他是稳定的,通过自身的克隆实现对象的创建。

四、模式的组成


      可以看出,在原型模式的结构图有以下角色:
(1)、原型类(Prototype):原型类,声明一个Clone自身的接口;
(2)、具体原型类(ConcretePrototype):实现一个Clone自身的操作。
    在原型模式中,Prototype通常提供一个包含Clone方法的接口,具体的原型ConcretePrototype使用Clone方法完成对象的创建。

五、 原型模式的具体实现

假设在一些打斗游戏场景中,有这样一些角色,普通(NormalActor),可以飞的(FlyActor).

//抽象原型(相当于工厂)
public abstract class NormalActor
{
public abstract NormalActor Clone();
} public abstract class FlyActor
{
public abstract FlyActor Clone();
} //具体实现
public class NormalActorA : NormalActor
{
public override NormalActor Clone()
{
return (NormalActor)this.MemberwiseClone();
}
} public class FlyActorA : FlyActor
{
public override FlyActor Clone()
{
return (FlyActor)this.MemberwiseClone();
}
}

客户程序:

public class GameSystem
{
public void Run(NormalActor normalActor, FlyActor flyactor)//如果把参数定义成属性也可以的不影响设计模式的实现。
{
//需要3个小兵
NormalActor noramlActor1 = normalActor.Clone();//克隆
NormalActor noramlActor2 = normalActor.Clone();
NormalActor noramlActor3 = normalActor.Clone();
//需要两个飞人
FlyActor flyActor1 = flyactor.Clone();
FlyActor flyActor2 = flyactor.Clone();
}
}

应用程序:

internal class App
{
public static void Main()
{
GameSystem gamesystem = new GameSystem();
gamesystem.Run(new NormalActorA(), new FlyActorA(), new FlyActorA());
}
}

有一点要注意,MemberwiseClone方法只是一种浅拷贝,它只能拷贝所有的值类型和String,如果是引用类型(例如数组),它就会只拷贝引用,而不会重新创建对象,例如对数组,就只会拷贝数组的地址。

六、原型模式的实现要点:

  Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。
  Prototype模式对于“如何创建易变类的实体对象”(创建型模式除了Singleton模式以外,都是用于解决创建易变类的实体对象的问题的)采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断地Clone。
  Prototype模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。

1、原型模式的优点:

(1)、原型模式向客户隐藏了创建新实例的复杂性
        (2)、原型模式允许动态增加或较少产品类。
        (3)、原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
        (4)、产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构

2、原型模式的缺点:

(1)、每个类必须配备一个克隆方法
       (2)、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

3、原型模式使用的场景:

(1)、资源优化场景
                      类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
         (2)、性能和安全要求的场景
                    通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
         (3)、一个对象多个修改者的场景
                    一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
           在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。

七、.NET 中原型模式的实现

在.NET中,微软已经为我们提供了原型模式的接口实现,该接口就是ICloneable,其实这个接口就是抽象原型,提供克隆方法,相当于与上面代码中Prototype抽象类,其中的Clone()方法来实现原型模式,如果我们想我们自定义的类具有克隆的功能,首先定义类实现ICloneable接口的Clone方法。其实在.NET中实现了ICloneable接口的类有很多

八、创建型模式的总结

Singleton模式解决的是实体对象个数的问题。除了Singleton之外,其他创建型模式解决的都是new所带来的耦合关系。
      Factory Method,Abstract Factory,Builder都需要一个额外的工厂类来负责实例化“易变对象”,而Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”。(其实原型就是一个特殊的工厂类,它只是把工厂和实体对象耦合在一起了)
如果遇到“易变类”,起初的设计通常从Factory Method开始,当遇到更多的复杂变化时,再考虑重构为其他三种工厂模式(Abstract Factory,Builder,Prototype)。
      一般来说,如果可以使用Factory Method,那么一定可以使用Prototype。但是Prototype的使用情况一般是在类比较容易克隆的条件之上,如果是每个类实现比较简单,都可以只用实现MemberwiseClone,没有引用类型的深拷贝,那么就更适合了。Prototype如果要实现深拷贝,还需要在每个要克隆的类上加序列化标签,这点复杂度要考虑进程序中。

创建型模式(五) 原型模式(Prototype)的更多相关文章

  1. 创建型设计模式之原型模式(Prototype)

    结构   意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 适用性 当要实例化的类是在运行时刻指定时,例如,通过动态装载:或者 为了避免创建一个与产品类层次平行的工厂类层次时:或 ...

  2. 建造者模式与原型模式/builder模式与prototype模式/创建型模式

    建造者模式 定义 用于简化复杂对象的创建 JDK中的建造者模式 java.lang.StringBuilder中的append()方法,每次调用后返回修改后的对象本身. public StringBu ...

  3. [19/04/24-星期三] GOF23_创建型模式(建造者模式、原型模式)

    一.建造者模式 本质:分离了对象子组件的单独构造(由Builder负责)和装配的分离(由Director负责),从而可以构建出复杂的对象,这个模式适用于:某个对象的构建过程十分复杂 好处:由于构建和装 ...

  4. 设计模式10---设计模式之原型模式(Prototype)

    1.场景模式 考虑这样一个实际应用:订单处理系统 里面有一个保存订单的功能,当产品数量超过1000份以后,拆成两份订单,再超,那么就再拆.直到每份订单不超过1000为止,订单有两种,一个是个人订单,一 ...

  5. 初涉JavaScript模式 (5) : 原型模式 【一】

    什么是原型模式? 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象.--引自JavaScript设计模式 我们创建的每一个函数都有一个prototype ...

  6. Java进阶篇设计模式之三 ----- 建造者模式和原型模式

    前言 在上一篇中我们学习了工厂模式,介绍了简单工厂模式.工厂方法和抽象工厂模式.本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式. 建造者模式 简介 建造者模式是属于创建型模式.建造者模式使用 ...

  7. 【js基础】创建对象的几种常见模式(工厂模式,构造函数模式,原型模式,构造原型组合模式)

    一.工厂模式 缺点:没有解决对象识别的问题 优点:解决了创建多个相似对象的问题 function createPerson(name,age,job){ var o = new Object(); o ...

  8. Java设计模式之三 ----- 建造者模式和原型模式

    前言 在上一篇中我们学习了工厂模式,介绍了简单工厂模式.工厂方法和抽象工厂模式.本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式. 建造者模式 简介 建造者模式是属于创建型模式.建造者模式使用 ...

  9. javascript 面向对象编程(工厂模式、构造函数模式、原型模式)

      javascript 面向对象编程(工厂模式.构造函数模式.原型模式) CreateTime--2018年3月29日17:09:38 Author:Marydon 一.工厂模式 /** * 工厂模 ...

随机推荐

  1. qmake, makefile, make是什么东东,makefile简介!

    qmake是一个协助简化跨平台开发的构建过程 的工具,Qt附带的工具之一 .qmake能够自动生成Makefile.Microsoft Visual Studio 专案文件 和 xcode 专案文件. ...

  2. Delphi Sysem.JSON 链式写法

    链式写法有很多优点:连贯.语意集中.简洁.一气呵成.可读性强.比如要把 3.1415926 中的 59 提取为一个整数:Pi.ToString().Substring(5,2).ToInteger() ...

  3. leetcode tree相关题目总结

    leetcode tree相关题目小结 所使用的方法不外乎递归,DFS,BFS. 1. 题100 Same Tree Given two binary trees, write a function ...

  4. es6新特性-解构表达式、Lambda表达式、局部变量及map/reduce方法

    循环内的变量在循环外可见,不合理: let定义的变量是局部变量: const修饰的是常量,不允许再次修改,类似于java中的static: 解构表达式:

  5. Spring MVC异常处理代码完整实例

    Spring MVC异常处理流程: 提供构造方法传值: 配置异常处理器的bean

  6. ColorMatrixFilter色彩矩阵滤镜

    ColorMatrixFilter色彩矩阵滤镜: /** * * *----------------------------------------* * | *** ColorMatrixFilte ...

  7. [LOJ3048] [十二省联考2019] 异或粽子

    题目链接 LOJ:https://loj.ac/problem/3048 洛谷:https://www.luogu.org/problemnew/show/P5283 Solution 考虑每个子串都 ...

  8. mysql数据库备份之主从同步配置

    主从同步意义? 主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器(slave).因为复制是异步进行的,所以从服务 ...

  9. 12 Mapping查询

    查看 某个index下所有type的mapping GET /beauties/_mapping 查看 指定index.指定type的mapping GET /beauties/_mapping/cn

  10. Linux下Java变量

    一.JAVA_HOME.PATH.CLASSPATH详解 1.1.JAVA_HOME 指向jdk安装目录,该目录下有bin.lib目录.Eclipse/NetBeans/Tomcat等软件就是通过搜索 ...