Sil*_*olt 40 design-patterns prototype-pattern
我正在学习不同的设计模式,我有一种强烈的感觉,我错过了理解这种特殊模式的必要部分(或部分).
在我查看的所有网站和GoF书中,我都看到了克隆方法.根据我的理解,当我们需要该对象的不同版本时,我们可以克隆某种类型的对象,但我们不希望使用"new"命令手动创建每个对象(如在Java中).这可以隐藏其具体实现.因此,当我们克隆时,我们可以稍微调整克隆并使其成为我们需要的,而不必知道如何最难创建该对象.这是我的想法吗?
我还被告知,这可以减少子类化,并随后减少您需要进行的类的数量.我不太明白这一部分.有人能帮助我掌握这个吗?
我的最后一个问题是抽象工厂(甚至工厂方法)模式.这些工厂模式和原型模式感觉就像他们试图在创建新对象时隐藏具体实现.什么时候选择其中一个是个好主意?
谢谢你们!
Dev*_*van 60
原型导致克隆对象与原始对象不同.在克隆时,原始状态与克隆相同.此后,每个对象可能经历状态改变.您可以将此视为类似的复印原件,然后在几个地方修改复印件.
例
优点
MemberwiseClose()
执行深层复制.什么时候使用它
与工厂模式的比较
原型模式允许对象创建自定义对象,而无需了解其类或如何创建它们的任何细节.所以,正是这个方面看起来很像工厂方法模式.在这两种模式中,客户端可以创建任何派生类对象,而无需了解自己的结构.
但是这两种模式之间的区别在于,Factory Method
专注于创建一个非现有对象类型的对象作为fresh creation
(通过理解Creator类的确切子类型).该Prototype
模式使用类本身,尤其是派生类来执行self duplication
操作.
在此模式中,客户端(或消费者)向创建者(或工厂)请求类层次结构中的特定类型的对象.工厂类的Creator方法将特定对象的创建委托给派生类,并返回客户端所请求类型的类的对象.实质上,您可以通过单点联系来创建类层次结构的多个对象.
您可以将此视为前往机票柜台(控制器)并通过提供您对机票类型(头等舱,行政人员或经济舱)的偏好来要求机票.用户不关心如何生成票证,即使在对象表示中,第一类和经济票据都是从基本票类派生的.
何时使用
已存在特定的Factory类.但工厂的方法略有不同.每种方法都可以生成一个实例.客户端可以选择适当的方法并获取实例.
如果您以MVC为基础的完美建筑设计示例,客户将成为业务控制器类,而混凝土产品将成为业务实体.工厂是辅助(辅助)控制器.它们与业务控制器的请求相关联.
何时使用
Tom*_*ing 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;
Run Code Online (Sandbox Code Playgroud)
因此,而不是子类化你要写的地方,new DirtBlock
或者new StoneBlock
你会写prototypes.dirt.clone()
或prototypes.stone.clone()
.不需要子类化,但如果需要,您仍然可以选择子类化.
至于何时选择原型模式而不是工厂模式,有两种情况我可以想到它们的不同之处:
您可以迭代原型列表,但不能迭代抽象工厂上的所有方法^.继续上面的代码,您可以创建一个随机块,如下所示:
prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();
如果您使用工厂方法来制作块,则获取随机块将更加困难.
在创建对象昂贵但复制便宜的情况下,原型模式将更有效.例如,采用此工厂方法:
Image loadUserImage() {
//loads from disk. will be slow
return new JPEGImage("path/to/user/image.jpg");
}
Run Code Online (Sandbox Code Playgroud)
如果要重复调用此方法,那么使用原型会更有效:
Image loadUserImage() {
//copy in memory. will be fast
return userImagePrototype.clone();
}
Run Code Online (Sandbox Code Playgroud)^这是一个白色谎言,因为你实际上可以根据你正在使用的语言迭代方法,但迭代数组仍然可能是一个更好的解决方案,因为它没有反射/内省复杂.
小智 15
在我看来,使用原型效率的提高是值得怀疑的.不会有效率提升,因为在大多数语言中,clone方法本身会执行对new的调用,以便构造自己的新对象实例.
我在使用原型模式时看到的唯一好处是方便,你知道克隆会给你一个对象的精确副本,这使你不必自己将新对象的属性设置为相同的值并且可能会挣扎深刻的副本.