何时使用工厂方法模式?
请提供一些具体的想法,什么情况下在项目中使用它?以及它如何比使用 new 关键字更好?
何时使用工厂方法模式?
请提供一些具体的想法,什么情况下在项目中使用它?以及它如何比使用 new 关键字更好?
当您希望重用不同组件的常见功能时,请使用工厂方法(而不是抽象工厂)。
示例:想象一下,您有一支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.
}
}
您可能暂时对此感到满意,认为您不需要改变任何东西。但是当您必须在丛林中进行秘密夜间隐身任务时,您会意识到您的附件完全不适合。您真正需要的是夜视镜、丛林迷彩和榴弹发射器作为辅助武器。您将不得不从原始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并覆盖工厂方法即可。
我有两种情况经常使用它:
举例:
第一种情况可以是您想创建一个工厂来创建 SqlCommand
对象,在返回命令对象之前自动附加有效的 SqlConnection
。
第二种情况是如果您定义了一个接口,并在执行时确定要使用哪个精确的接口实现(例如通过在配置文件中指定)。
DO:更倾向于使用构造函数而不是工厂方法,因为它们通常比特定的创建机制更易用、一致和方便。
CONSIDER:如果需要比构造函数更多的控制来创建实例,则可以考虑使用工厂方法。
DO:在开发人员可能不知道要构造哪种类型(例如针对基类或接口编码)的情况下使用工厂方法。
CONSIDER:当只有通过一个命名方法才能使操作变得清晰明了时,可以考虑使用工厂方法。
DO:对于转换式操作,请使用工厂方法。
此外,从第5.3节“构造函数设计”中可以得出以下建议:
CONSIDER:如果所需操作的语义不能直接映射到新实例的构造,或遵循构造函数设计准则感觉不自然,则可以考虑使用静态工厂方法。
尽管这不一定是它的主要用途,但它对于某些需要使用类的专门实例的情况非常有用:
public ITax BuildNewSalesTax()
public ITax BuildNewValueAddedTax()
您需要使用两种方法来构建一个税务对象,但是您不希望每次都依赖于使用 "new",因为构造函数可能很复杂。通过这种方式,我将所有更改封装在一个单独的方法中,以便于他人进行未来维护。
我在使用工厂模式时
当一个类不知道它必须创建哪个类的对象时。
一个类指定其子类以指定要创建哪些对象。
在程序员语言中(非常原始的形式),您可以使用工厂模式,在提供数据的情况下创建任何一个子类的对象之一。
当需要生成属于特定系列的对象时,可以使用工厂方法模式。除此之外,您还希望将有关对象实例化的决策集中在一个地方。
请参阅以下链接以获取更多详细信息。
http://xeon2k.wordpress.com/2010/11/27/factory-method-pattern/
当系统应该独立于其产品的创建、组合和表示方式时,使用抽象工厂模式。 当系统应配置为使用多个产品系列之一时。 当设计了一组相关的产品对象以一起使用,并且您需要强制执行此约束时。 当您想提供一个产品类库,并且只想公开它们的接口而不是实现时,请使用抽象工厂模式。
使用工厂方法模式而不是new关键字更好。其思想是将对象的完整实例化移出业务逻辑。这个原则是依赖注入的核心。而且,工厂方法的工作可以在以后委托给依赖注入框架,如Spring.net或Castle Windsor。
我认为这是当你希望你的应用程序在未来可以松散耦合和可扩展而无需进行编码更改时使用的。
我在博客上写了一篇关于为什么我在项目中选择工厂模式的文章,也许它可以给你更多的见解。示例是用PHP编写的,但我认为它通常适用于所有语言。
http://www.mixedwaves.com/2009/02/implementing-factory-design-pattern/