何时使用工厂方法模式?
Posted
技术标签:
【中文标题】何时使用工厂方法模式?【英文标题】:When to use Factory method pattern? 【发布时间】:2010-12-03 21:52:14 【问题描述】:什么时候使用工厂方法模式?
请给我一些具体的想法,什么时候在项目中使用它? 以及它如何比 new 关键字更好?
【问题讨论】:
【参考方案1】:当您想对不同组件重用通用功能时,请使用工厂方法(不是抽象工厂)。
示例:假设您有一支 M16 步枪。像这样的:
public class M16
private Scope scope = new StandardScope();
private SecondaryWeapon secondary = new Bayonet();
private Camouflage camo = new DesertCamo();
public double getMass()
// Add the mass of the gun to the mass of all the attachments.
public Point2D shootAtTarget(Point2D targetPosition)
// Very complicated calculation taking account of lots of variables such as
// scope accuracy and gun weight.
你可能会满意一段时间,认为你不会想要改变任何东西。但随后你必须在丛林中执行一项秘密的夜间隐身任务,然后你意识到你的依恋是完全不合适的。你真的需要夜视镜、JungleCamo 和 GrenadeLauncher 辅助武器。您将不得不从原始 M16 复制过去的代码......扩展性不好......工厂方法来救援!
重写你的 M16 类:
public abstract class M16
private Scope scope = getScope();
private SecondaryWeapon secondary = getSecondaryWeapon();
private Camouflage camo = getCamouflage();
public double getMass()
// Add the mass of the gun to the mass of all the attachments.
public Point2D shootAtTarget(Point2D targetPosition)
// Very complicated calculation taking account of lots of variables such as
// scope accuracy and gun weight.
// Don't have to be abstract if you want to have defaults.
protected abstract Scope getScope();
protected abstract SecondaryWeapon getSecondaryWeapon();
protected abstract Camouflage getCamouflage();
//Then, your new JungleM16 can be created with hardly any effort (and importantly, no code //copying):
public class JungleM16 : M16
public Scope getScope()
return new NightVisionScope();
public SecondaryWeapon getSecondaryWeapon()
return new GrenadeLauncher();
public Camouflage getCamouflage()
return new JungleCamo();
主要思想?自定义和交换组合对象,同时保持通用功能。
一个真正有用的地方: 您刚刚设计了一个非常酷的 GUI,它的布局非常复杂。如果您想拥有不同的小部件,则必须重新布局所有内容将是一件非常痛苦的事情。所以.....使用工厂方法来创建小部件。然后,如果您改变主意(或其他人想使用您的类,但使用不同的组件),您可以只将 GUI 子类化并覆盖工厂方法。
【讨论】:
嘿,这是一个很好的解释,你写过我喜欢阅读的教程吗..! 嘿伙计,很好的解释。这让我们更容易理解。干得好。 终于有了一个有意义的工厂模式。我看到了很多对代码库没有任何好处的非常糟糕的例子。【参考方案2】:我有两种情况我倾向于使用它:
-
对象需要以某种特定方式初始化
当我想基于抽象类型(抽象类或接口)构造特定类型时。
示例:
第一种情况可能是您希望有一个工厂创建SqlCommand
对象,在返回命令对象之前自动附加一个有效的SqlConnection
。
第二种情况是如果您定义了一个接口并在执行时确定要使用的接口的确切实现(例如通过在配置文件中指定它)。
【讨论】:
【参考方案3】:您可以参考框架设计指南第 2 版中的第 9.5 节工厂。以下是关于在构造函数上使用工厂的一组指南:
更喜欢构造函数 工厂,因为它们是 通常更可用,更一致, 比专业更方便 构造机制。
如果需要,请考虑使用工厂 更多的控制权 构造函数在创建 实例。
在以下情况下使用工厂 开发人员可能不知道哪种类型 构建,例如在编码时 针对基本类型或接口。
如果有工厂,请考虑使用工厂 命名方法是唯一的方法 操作一目了然。
务必使用工厂进行转换样式 操作。
从第 5.3 节构造函数设计开始
考虑使用静态工厂方法而不是构造函数,如果 所需操作的语义不直接映射到构造 化新实例,或者如果遵循构造函数设计指南 感觉不自然。
【讨论】:
【参考方案4】:虽然这不一定是它的主要用途,但它适用于您有专门的类实例的情况:
public ITax BuildNewSalesTax()
public ITax BuildNewValueAddedTax()
您需要这两种方法来构建税收对象,但您不希望每次都依赖于使用“new”,因为构造函数可能很复杂。通过这种方式,我将所有更改封装到一个方法中,其他人可以清楚地了解该方法以供将来维护。
【讨论】:
【参考方案5】:我在使用工厂模式时
当一个类不知道它必须创建哪个类的对象时。
一个类指定它的子类来指定要创建的对象。
在程序员的语言中(非常原始的形式),您可以使用工厂模式,您必须根据提供的数据创建任何一个子类的对象。
【讨论】:
【参考方案6】:当需要生成属于特定系列的对象时,可以使用工厂方法模式。除此要求外,您还希望将有关对象实例化的决定保留在一个地方。
更多详情请参考以下链接。
http://xeon2k.wordpress.com/2010/11/27/factory-method-pattern/
【讨论】:
【参考方案7】:在以下情况下使用抽象工厂模式 一个系统应该独立于其产品的创建、组合和表示方式。 一个系统应该配置有多个产品系列中的一个。 一系列相关的产品对象旨在一起使用,您需要强制执行此约束。 您想提供一个产品类库,并且只想显示它们的接口,而不是它们的实现。
【讨论】:
【参考方案8】:最好有工厂方法模式与新关键字。这个想法是将对象的完整实例化移到业务逻辑之外。这个原则是dependency injection的症结所在。而且,工厂方法的工作可以在以后委托给像 Spring.net 或 Castle Windsor 这样的依赖注入框架。
【讨论】:
我曾在一个代码库中工作,其中每个“新”都被工厂委托替换,完全 IoC 容器化。这是一场噩梦。经过 5 名开发人员一年半的开发,它被废弃了。 3 名开发人员使用行业标准实践在 1 个月内替换了该功能。根据我的经验,工厂在@Dzmitri 指出的情况下非常有用。除非您打算通过配置切换类型或具有非常有趣的构造函数逻辑,否则我认为用工厂替换 new 是矫枉过正且适得其反。【参考方案9】:从我的角度来回答你的第二部分问题,我认为它比'new'关键字更好的原因是工厂方法减少了对特定类的构造函数的依赖。通过使用工厂方法,您可以将相关对象的创建委托给其他人,因此调用者不需要知道如何创建对象。
【讨论】:
【参考方案10】:我认为当您希望您的应用程序在未来松散耦合和可扩展而无需更改编码时。
我在博客上写了一篇关于我为什么在我的项目中选择工厂模式的文章,也许它可以让你更深入地了解。该示例使用 php,但我认为它通常适用于所有语言。
http://www.mixedwaves.com/2009/02/implementing-factory-design-pattern/
【讨论】:
以上是关于何时使用工厂方法模式?的主要内容,如果未能解决你的问题,请参考以下文章