何时使用Factory方法模式?

时间:2009-10-05 10:46:40

标签: c# design-patterns factory

何时使用Factory方法模式?

请告诉我何时在项目中使用它? 以及它如何比新关键字更好?

11 个答案:

答案 0 :(得分:35)

我有两种情况我倾向于使用它:

  1. 需要以某种特定方式初始化对象
  2. 当我想基于抽象类型(抽象类或接口)构造特定类型时。
  3. <强>示例:

    1. 第一种情况可能是您希望工厂创建SqlCommand对象,在返回命令对象之前自动附加有效SqlConnection。< / p>

    2. 第二种情况是指您定义了一个接口,并在执行时确定要使用的接口的确切实现(例如,通过在配置文件中指定它)。

答案 1 :(得分:34)

如果要重用不同组件的常用功能,请使用工厂方法(非抽象工厂)。

示例:想象一下你有一把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.
    }
}

你可能会对它感到满意,认为你不想改变任何东西。但是你必须在丛林中做一个秘密的夜间秘密任务,你会发现你的附件是完全不合适的。你真的需要一个NightVision范围,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 :(得分:24)

您可以参阅第9.5节“框架设计指南第2版”中的“工厂”。以下是关于使用工厂而不是构造函数的引用指南:

  

更喜欢施工人员   工厂,因为他们是   通常更有用,更一致,   比专业方便   建设机制。

     

如果需要,请考虑使用工厂   比可以提供更多的控制   建设者在创造   实例

     

在a的情况下,请使用工厂   开发人员可能不知道哪种类型   构造,例如编码时   对基本类型或接口。

     

如果有工厂,请考虑使用工厂   命名方法是唯一的方法   操作不言自明。

     

请使用工厂进行转换   操作

从第5.3节“构造函数设计”

开始
  

CONSIDER使用静态工厂方法而不是构造函数   所需操作的语义不直接映射到构造 -   一个新实例,或者如果遵循构造函数设计指南   感觉不自然。

答案 3 :(得分:16)

虽然这不一定是它的主要用途,但对于你有专门的类实例的东西是好的:

public ITax BuildNewSalesTax()
public ITax BuildNewValueAddedTax()

您需要两种方法来构建税对象,但您不希望每次都依赖于使用“new”,因为构造函数可能很复杂。通过这种方式,我将所有更改封装到一个方法中,这个方法对于其他人来说是清楚的,以便将来进行维护。

答案 4 :(得分:6)

我在

时使用工厂图案
  1. 当一个类不知道它必须创建哪个类对象时。

  2. 类指定其子类以指定要创建的对象。

  3. 在程序员的语言(非常原始的形式)中,您可以使用工厂模式,您必须根据提供的数据创建任何一个子类的对象。

答案 5 :(得分:3)

当需要生成属于特定族的对象时,可以使用工厂方法模式。除此要求外,您还希望在一个地方保留有关对象实例化的决策。

有关详细信息,请参阅以下链接。

http://xeon2k.wordpress.com/2010/11/27/factory-method-pattern/

答案 6 :(得分:2)

何时使用抽象工厂模式 系统应独立于其产品的创建,组合和表示方式。 系统应配置多个产品系列之一。 一系列相关产品对象旨在一起使用,您需要强制执行此约束。 你想提供一个产品类库,你想要只揭示它们的接口,而不是它们的实现。

答案 7 :(得分:2)

工厂模式处理对象的实例化而不暴露实例化逻辑。换句话说,Factory实际上是具有公共接口的对象的创建者。

它允许子类决定要实例化哪个类。

考虑以下示例:

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //Store is ordering the factory to get office shoes
            Shoe shoe = ShoeFactory.GetShoes("OFFICE");
            Console.WriteLine(shoe.GetType()); //Will be office shoes

            //Store is ordering the factory to get sports shoes
            shoe = ShoeFactory.GetShoes("SPORTS");
            Console.WriteLine(shoe.GetType()); //Will be sports shoes
        }
    }

    //This is the factory supplying shoes. It can supply sports shoes or office shoes
    //based on demand
    class ShoeFactory
    {
        public static Shoe GetShoes(string strShoeType)
        {
            switch (strShoeType)
            {
                case "SPORTS": return new SportShoe();
                    break;
                case "OFFICE": return new OfficeShoe();
                    break;
                default:
                    return null;
            }
        }
    }

    //This is an abstract class representing product family
    //In this example, its shoe
    public abstract class Shoe
    {

    }

    //Office shoe is a concrete class belongs to shoe family
    class OfficeShoe : Shoe
    {   

    }

    //Sports shoe is a concrete class belongs to shoe family
    class SportShoe : Shoe
    {

    }
}

答案 8 :(得分:1)

最好有一个工厂方法模式与新关键字。我们的想法是在业务逻辑之外移动对象的完整实例化。这个原则是dependency injection的关键。并且,工厂方法的工作可以稍后委托给Spring.net或Castle Windsor等依赖注入框架。

答案 9 :(得分:-1)

从我的观点回答你问题的第二部分,我认为它比'new'关键字更好的原因是工厂方法降低了对特定类的构造函数的依赖性。通过使用工厂方法,您可以将相关对象的创建委托给其他人,因此调用者不需要知道如何创建对象。

答案 10 :(得分:-2)

我认为,当您希望应用程序在未来编码更改时可以松散耦合和扩展时。

我在博客上发了一篇文章,说明为什么我在项目中选择工厂模式,可能会给你更多的见解。这个例子是在PHP中,但我认为它适用于所有语言。

http://www.mixedwaves.com/2009/02/implementing-factory-design-pattern/