关于原型模式的问题

时间:2011-04-21 03:38:13

标签: design-patterns prototype-pattern

我正在学习不同的设计模式,我有一种强烈的感觉,我在理解这种特殊模式时缺少必要的部分(或部分)。

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

我还被告知,这可以减少子类化,并随后减少您需要制作的类的数量。我不太明白这一部分。有人能帮助我掌握这个吗?

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

谢谢大家!

3 个答案:

答案 0 :(得分:60)

答案 1 :(得分:27)

你有原型模式的外观。

如何减少子类化

让我们说你正在制作MineCraft并且你正在使用每种不同类型的块(例如泥土,石头等)的原型模式。所有原型对象实际上都是同一个类Block,但是每个对象都设置了不同的属性,因此它的外观和行为都不同,例如:

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;

因此,您可以改为编写new DirtBlocknew StoneBlock,而不是将prototypes.dirt.clone()prototypes.stone.clone()写入子类。不需要子类化,但如果需要,您仍然可以选择子类化。

与工厂模式的差异

至于何时选择原型模式而不是工厂模式,我可以想到两种不同的情况:

  1. 您可以迭代原型列表,但不能迭代抽象工厂上的所有方法^。继续上面的代码,你可以像这样创建一个随机块:

    prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();

    如果您使用工厂方法来制作块,那么获取随机块将更加困难。

  2. 如果对象的创建很昂贵,但复制很便宜,原型模式会更高效。例如,采用此工厂方法:

    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();
    }
    

  3. ^这是一个白色谎言,因为你实际上可以根据你正在使用的语言迭代方法,但迭代数组仍然可能是一个更好的解决方案,因为它不如反射/内省复杂。

答案 2 :(得分:15)

在我看来,使用原型效率的提高是值得怀疑的。不会有效率提升,因为在大多数语言中,clone方法本身会执行对new的调用,以便构造自己的新对象实例。

我在使用原型模式时看到的唯一好处是方便,你知道克隆会给你一个对象的精确副本,这使你不必自己设置新对象的属性为相同的值并且可能在深刻的复制中挣扎。