Design patterns 关于原型模式的问题

Design patterns 关于原型模式的问题,design-patterns,prototype-pattern,Design Patterns,Prototype Pattern,我正在学习不同的设计模式,我有一种强烈的感觉,在理解这个特定的模式时,我错过了一个(或多个)重要的部分 在我浏览过的所有网站和GoF书籍中,我都看到了克隆方法。据我所知,当我们需要不同版本的对象时,我们可以克隆某些类型的对象,但我们不希望必须使用“new”命令手动创建每个对象(如在Java中)。这可能会隐藏其具体实现。因此,当我们克隆时,我们可以稍微调整克隆,使其成为我们所需要的,而不必知道最初如何艰难地创建该对象。这是我的想法吗 我还被告知,这可以减少子类化,从而减少需要创建的类的数量。这部分

我正在学习不同的设计模式,我有一种强烈的感觉,在理解这个特定的模式时,我错过了一个(或多个)重要的部分

在我浏览过的所有网站和GoF书籍中,我都看到了克隆方法。据我所知,当我们需要不同版本的对象时,我们可以克隆某些类型的对象,但我们不希望必须使用“new”命令手动创建每个对象(如在Java中)。这可能会隐藏其具体实现。因此,当我们克隆时,我们可以稍微调整克隆,使其成为我们所需要的,而不必知道最初如何艰难地创建该对象。这是我的想法吗

我还被告知,这可以减少子类化,从而减少需要创建的类的数量。这部分我不太懂。有人能帮我抓住这个吗

我的最后一个问题是关于抽象工厂(甚至工厂方法)模式。这些工厂模式和原型模式感觉像是试图在创建新对象时隐藏具体的实现。什么时候选择其中一个是好主意

谢谢大家!

原型模式 原型生成的克隆对象与原始对象不同。克隆时,原始的状态与克隆的状态相同。此后,每个对象都可能经历状态变化。你可以把这看作是一种类似于复印原件,然后在一些地方修改复印件的事情。 范例

  • DVD复制:复制主DVD以创建多个副本
  • Re>报表对象:考虑包含要传递给GUI的处理信息的报表对象。原始报告按升序包含数据。现在,使用此模式可以创建一个类似的报告,但数据按降序排序
利益

  • 性能:克隆(使用)要比重新创建新对象(使用)便宜得多。请注意,需要重写
    MemberwiseClose()
    以执行深度复制
  • 对象可以非常动态地克隆,而无需预先实例化。第一个创建的对象可以在应用程序执行过程中的任何时候创建,进一步的复制可以在任何时候进行
什么时候使用它

  • 当在运行时指定要实例化的类时,例如,通过动态加载
  • 当一个类的实例只能有几个不同的状态组合中的一个时。安装相应数量的原型并克隆它们可能比手动实例化类更方便,每次都使用适当的状态
与工厂模式的比较

原型模式允许对象创建自定义对象,而不知道它们的类或如何创建它们的任何细节。所以,这方面看起来很像工厂方法模式。在这两种模式中,客户机可以创建任何派生类对象,而不必知道它们自己的结构

但这两种模式之间的区别在于,
工厂方法
专注于创建一个不存在的对象类型的对象作为
新创建
(通过理解创建者类的确切子类型)。
Prototype
模式使用类本身,尤其是派生类来执行
自复制
操作


工厂方法模式 在此模式中,客户机(或使用者)要求创建者(或工厂)从类层次结构中获取特定类型的对象。factory类的Creator方法将特定对象的创建委托给派生类,并返回客户机要求的类型的类的对象。本质上,创建一个类层次结构的多个对象只有一个接触点。 你可以把这看作是去机票柜台(管制员)询问机票类型(头等舱、行政舱或经济舱)。用户不关心票证是如何生成的,即使在对象表示中,头等舱和经济舱票证都是从基本票证类派生的

何时使用

  • 灵活性很重要(低耦合)
  • 对象可以在子类中扩展
  • 为什么选择一个子类而不是另一个子类,有一个特定的原因。这个逻辑构成工厂方法的一部分
  • 客户机将职责委托给并行层次结构中的子类

抽象工厂模式 抽象工厂比工厂方法模式更高(更抽象)。在这种情况下,一个工厂不仅可以有一个,还可以有多个工厂,但略有不同。它负责创建属于类层次结构族的对象,而不仅仅是单个类层次结构

特定的工厂类已存在。但工厂将有略微不同的方法。每个方法都可以生成一个实例。客户端可以选择合适的方法并获取实例

如果您以基于完美架构设计为例,那么客户机将是一个业务控制器类,而具体产品将全部是业务实体。工厂是辅助(辅助)控制器。它们与来自业务控制器的请求协同工作

何时使用

  • 该系统预计将独立于其产品的创建方式。它甚至可能期望独立于产品的组成和表示方式。术语产品适用于最终生成的对象,客户机开发人员需要通过调用其方法来使用该对象
  • 应可配置多个产品系列之一的系统。所以实际选择
    prototypes.dirt = new Block;
    prototypes.dirt.texture = new Image("dirt.jpg");
    prototypes.dirt.hardness = 1;
    
    prototypes.stone = new Block;
    prototypes.stone.texture = new Image("stone.jpg");
    prototypes.stone.hardness = 9;
    
    Image loadUserImage() { 
        //loads from disk. will be slow
        return new JPEGImage("path/to/user/image.jpg"); 
    }
    
    Image loadUserImage() {
        //copy in memory. will be fast
        return userImagePrototype.clone();
    }