问题描述
我正在学习不同的设计模式,并且有一种强烈的感觉,我缺少理解这种特殊模式的必不可少的作品(或作品).
在我查看的所有网站和GOF书中,我看到了克隆方法.据我了解,我们有某种类型的对象,当我们需要该对象的变化版本时,我们可以克隆,但是我们不想使用"新"命令(如Java中)手动创建每个对象.这可以隐藏其具体的实现.因此,当我们克隆时,我们可以对克隆进行一些调整,并使其成为我们所需的内容,而无需知道如何最初以困难的方式创建该对象.这是我的想法正确吗?
我还被告知,这可以减少子分类,然后减少您需要进行的课程数量.我不太了解这部分.有人可以帮我掌握吗?
我的最后一个问题是关于抽象工厂(甚至工厂方法)模式.这些工厂模式和原型模式感觉就像是在创建新对象时试图隐藏具体的实现.选择另一个是一个好主意?
谢谢大家!
推荐答案
原型模式
原型导致克隆对象与原始对象不同.在克隆时,原始状态与克隆相同.此后,每个对象可能会发生状态变化.您可以将其视为类似的影印本,然后在几个地方修改影印本.示例
- DVD重复:主DVD的复制以创建多个副本
- 报告对象:考虑一个报告对象,其中包含要传递给GUI的已处理信息.原始报告包含升序顺序的数据.现在,使用这种模式可以创建类似的报告,但以降序排序数据.
好处
- 性能:克隆(使用成员Wisececlone ">要比重新创建一个新对象要便宜得多(使用新操作员 ).请注意,需要覆盖MemberwiseClose()才能执行深层副本.
- 对象可以非常动态克隆,而无需任何预先实例化.可以在应用程序执行中的任何时候创建第一个创建的对象,并且可以在下一步的任何时间进行进一步的重复.
何时使用它
- 当运行时指定实例化的类时,例如通过动态加载.
- 班级实例只能拥有仅有几种不同状态组合之一.安装相应数量的原型并克隆它们,而不是每次使用适当的状态进行手动实例化可能更方便.
与工厂模式进行比较
原型模式允许对象创建自定义对象,而无需知道其类或如何创建它们的任何细节.因此,正是这一方面似乎很像出厂方法模式.在这两种模式中,客户端都可以创建任何派生的类对象,而无需了解自己的结构.
但是,两种模式之间的区别在于,Factory Method集中于创建一个非现有对象类型的一个对象作为fresh creation(通过了解创建者类的确切子类型). Prototype模式使用类本身,尤其是self duplication action的派生类.
工厂方法模式
在这种模式下,客户(或消费者)向创建者(或工厂)询问类层次结构的特定对象.工厂类的创建者方法将特定对象的创建委派给了派生类,并返回客户端要求的类型的对象.从本质上讲,您可以单点联系,以创建类层次结构的几个对象.您可以将其视为去航空公司票务柜台(控制器),并通过偏爱门票类型(头等舱,执行或经济)来要求票.用户不关心票证的生成,即使在对象表示中,第一类和经济票都来自基本票务类.
何时使用
- 灵活性很重要(低耦合)
- 可以在子类中扩展对象
- 有一个特定原因为什么选择一个子类要选择另一个子类 - 该逻辑构成了工厂方法的一部分.
- 客户委员会委派对并行层次结构中的子类别的责任.
抽象工厂模式
抽象工厂比工厂方法模式高(更抽象).在这种情况下,一个人不仅可以拥有一个略有变化的多个工厂.它负责创建属于阶级层次结构的属于的对象,而不仅仅是单个类层次结构.已经存在特定的工厂课程.但是工厂的方法将有些不同.每种方法都可以产生一个实例.客户端可以选择适当的方法并获取实例.
如果您以 mvc 基于完美的建筑设计,客户将是业务控制器类,而混凝土产品将是业务实体.工厂是辅助(助手)控制器.他们与业务控制器的请求合作.
何时使用
- 预计该系统将独立于其产品的创建方式.它甚至可以期望产品如何组成和代表.该术语产品适用于客户开发人员需要通过调用其方法来使用的最终结果对象.
- 应该与多个产品系列之一配置的系统.因此,家庭的实际选择不会在编码时间,而是在以后的配置时.
- 产品家族旨在始终一起工作.
- 创建适用于产品库.这里更关心的是相关界面,而不是实现.
其他推荐答案
您的外观正确地拥有了原型图案.
它如何减少子分类
假设您正在制作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 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"); }
如果要重复调用此方法,使用这样的原型将更有效:
:Image loadUserImage() { //copy in memory. will be fast return userImagePrototype.clone(); }
^这是一个白色的谎言,因为您实际上可以根据使用的语言迭代方法,但是在数组上进行迭代可能仍然是一个更好的解决方案,因为它不如反射/内省.
其他推荐答案
在我看来,使用原型的效率提高是值得怀疑的.不会有效率增益,因为在大多数语言中,克隆方法本身都执行了对新的调用,以构建自身的新对象实例.
我在使用原型模式时看到的唯一好处是便利性,您知道克隆会为您提供一个确切的对象的副本,使您不得不将新对象的属性设置为同一值自己并可能与深层复制斗争.
问题描述
I am learning about the different design patterns and I have a strong feeling I am missing an essential piece (or pieces) in understanding this particular pattern.
In all the websites I have viewed and in the GoF book, I see the clone method. From what I understand, we have some type of object that we can clone when we need varying versions of that object, but we don't want to have to manually create each one using the "new" command (as in Java). This can hide its concrete implementation. So when we clone, we can tweak the clone just a little bit and make it what we need without having to knowing how to originally create that object the hard way. Is this my thinking correct?
I am also told that this can reduce subclassing and subsequently reduce the number of classes you need to make. I don't quite understand this part. Could someone help me grasp this?
My final question is about the abstract factory (or even the factory method) pattern. These factory patterns and the prototype pattern feel like they attempt to hide concrete implementations upon creation of new objects. When is it a good idea to choose one of the other?
Thank you all!
推荐答案
Prototype pattern
Prototype results in a cloned object which is different from the original object. The state of the original is the same as the clone, at the time of cloning. Thereafter each object may undergo state change. You can think of this as something similar photocopying the original and then modifying the photocopy at a few places.Example
- DVD duplication: Duplication of the master dvd to create several copies
- Reporting object: Consider a report object that contains processed information to be passed to the GUI. The original report contains the data in ascending order. Now, using this pattern one can create a similar report but with data sorted in descending order.
Benefits
- Performance: Cloning (using MemberwiseClone) is considerably less expensive than creating a new object afresh (with new operator). Note that one needs to override the MemberwiseClose() to perform a deep copy.
- Objects can be cloned very dynamically, without any insistence on up-front instantiation. The first created object can be created at any time in the application execution, and further duplication can take place at any time ahead.
When to use it
- When the classes to instantiate are specified at run-time, for example, by dynamic loading.
- When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.
Comparison with Factory Pattern
Prototype pattern allows an object to create customized objects without knowing their class or any details of how to create them. So, it is this aspect it appears to be a lot like the Factory Method pattern. In both these patterns, the client can create any of the derived class objects without knowing anything about their own structure.
But the difference between the two patterns is the fact that the Factory Method concentrates on creating one object of a non existing object type as a fresh creation (by understanding the exact sub-type of the Creator class). The Prototype pattern uses the class itself, especially the derived class for self duplication action.
Factory Method pattern
In this pattern, the client (or consumer) asks the Creator (or factory) for a specific type of object from a class hierarchy. The Creator method of the factory class delegates the creation of the specific object to the derived classes and returns the object of the class of the type asked by client. In essence, you have a single point of contact for the creation of several objects of a class hierarchy.You can think of this as going to an airline ticket counter (controller) and asking for a ticket by giving your preference of the ticket type (first class, executive or economy). The user is not concerned with how the ticket is being generated, even though in an object representation the first class and the economy ticket are both derived from the base ticket class.
When to use
- Flexibility is important (low coupling)
- Objects can be extended in subclasses
- There is a specific reason why one subclass would be chosen over another—this logic forms part of the Factory Method.
- A client delegates responsibilities to subclasses in parallel hierarchies.
Abstract factory pattern
Abstract factory goes a step higher (more abstract) than the factory method pattern. In this case, one can have not just a single, but multiple factories with slight variations. It is responsible for creating objects belonging families of class hierarchies rather than just a single class hierarchy.A specific Factory class already exists. But the Factory will have slightly varying methods. Each method can produce an instance. The client can choose appropriate method and get the instance.
If you take the example of MVC based perfect Architectural Design, the client will be a Business Controller Class while Concrete Products will all be Business Entities. The Factories are Auxiliary ( Helper) Controllers. They work in association with a request from the Business Controller.
When to use
- The system is expected to be independent of how its products are created. It may even expect independence on how the products are composed and represented. The term product applies to the finally resulting object that a client developer would need to make use of by invoking its methods.
- The system that should be configurable with one of the multiple families of products. So the actual selection of the family will not be at coding time but at a later configuration time.
- The family of products is designed to work always together.
- The creation is for a library of products. What is cared more here is the relevant interface and not the implementation.
其他推荐答案
You've got the prototype pattern right by the looks of it.
How it Reduces Subclassing
Lets say you're making MineCraft and you're using the prototype pattern for each different kind of block (e.g. dirt, stone, etc). All the prototype objects are actually of the same class Block, but each object has had different properties set on it so that it looks and behaves differently, for example:
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;
So instead of subclassing where you would write new DirtBlock or new StoneBlock, you would instead write prototypes.dirt.clone() or prototypes.stone.clone(). No subclassing is required, but you still have the option to subclass if need be.
Differences With Factory Pattern
As for when to choose the prototype pattern instead of a factory pattern, there are two situations I can think of where they differ:
You can iterate over a list of prototypes, but you can't iterate over all the methods on an abstract factory^. Continuing from the code above, you could create a random block like so:
prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();
If you were using the factory method to make blocks, it would be harder to get a random block.
Where creation of an object is expensive, but copying is cheap, the prototype pattern will be more efficient. For example, take this factory method:
Image loadUserImage() { //loads from disk. will be slow return new JPEGImage("path/to/user/image.jpg"); }
If this method is going to be called repeatedly, it would be more efficient to use a prototype like so:
Image loadUserImage() { //copy in memory. will be fast return userImagePrototype.clone(); }
^ This is a white lie because you actually can iterate over methods depending on what language you're using, but iterating over an array is still probably a better solution because it's less complex than reflection/introspection.
其他推荐答案
The gain in efficiency of using a prototype is questionable in my mind. There will be no efficiency gain because in most languages the clone method itself executes a call to new in order to construct a new object instance of itself.
The only benefit that I see in using the prototype pattern is one of convenience, you know that clone will give you an exact copy of the object which frees you from having to set the attributes of the new object to the same values yourself and possibly struggling with deep copy.