web-dev-qa-db-ja.com

ファクトリメソッドパターンを使用する場合

ファクトリメソッドパターンを使用する場合

プロジェクトで使用する場合の具体的なアイデアを教えてください。そしてそれはどのように新しいキーワードより良い方法ですか?

34
Jaswant Agarwal

これは必ずしも主な用途ではありませんが、クラスの特殊なインスタンスがある場合に適しています。

public ITax BuildNewSalesTax()
public ITax BuildNewValueAddedTax()

税オブジェクトを作成するには両方のメソッドが必要ですが、コンストラクターが複雑になる可能性があるため、毎回「new」を使用する必要はありません。このようにして、すべての変更を単一のメソッドにカプセル化し、将来のメンテナンスのために他のユーザーにわかりやすくします。

18
Austin

私はそれを使用する傾向がある2つのケースがあります。

  1. オブジェクトは特定の方法で初期化する必要があります
  2. 抽象型(抽象クラ​​スまたはインターフェイス)に基づいて特定の型を構築する場合。

例:

  1. 最初のケースは、有効なSqlCommandを自動的にアタッチするSqlConnectionオブジェクトをファクトリで作成する場合があります。コマンドオブジェクトを返す前。

  2. 2番目のケースは、インターフェースが定義されていて、実行時にどのインターフェースの正確な実装を使用するかを決定する場合(例えば、構成ファイルで指定することにより) )。

36
Fredrik Mörk

さまざまなコンポーネントで共通の機能を再利用する場合は、(抽象ファクトリではなく)ファクトリメソッドを使用します。

例: 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をサブクラス化してファクトリメソッドをオーバーライドするだけです。

36
Kevin

フレームワーク設計ガイドライン第2版のセクション9.5ファクトリを参照できます。以下は、コンストラクターでのファクトリーの使用に関するガイドラインの引用セットです。

コンストラクタは、一般的に、特殊な構築メカニズムよりも使いやすく、一貫性があり、便利なので、ファクトリよりもコンストラクタを優先します。

インスタンスの作成に関してコンストラクターで提供できる以上の制御が必要な場合は、ファクトリーを使用することを検討してください。

基本タイプまたはインターフェースに対してコーディングする場合など、開発者が構築するタイプを知らない可能性がある場合は、ファクトリーを使用してください。

名前付きのメソッドがある場合はファクトリを使用することを検討することは、操作を自明にする唯一の方法です。

変換スタイルの操作にはファクトリを使用してください。

そして、セクション5.3コンストラクタの設計から

目的の操作のセマンティクスが新しいインスタンスの構成に直接マッピングされない場合、またはコンストラクターの設計ガイドラインに従うことが不自然であると感じる場合は、コンストラクターの代わりに静的ファクトリーメソッドを使用するCONSIDER。

24
Dzmitry Huba

Factory pattensを使用しているとき

  1. クラスが作成する必要があるオブジェクトのクラスがわからない場合。

  2. クラスはそのサブクラスを指定して、作成するオブジェクトを指定します。

  3. プログラマーの言語(非常に生の形式)では、提供されたデータに応じてサブクラスのいずれかのオブジェクトを作成する必要があるファクトリパターンを使用できます。

6
Dhrumil Shah

ファクトリメソッドパターンは、特定のファミリに属する​​オブジェクトを生成する必要がある場合に使用できます。この要件に加えて、オブジェクトのインスタンス化に関して行われた決定も1か所に保持する必要があります。

詳細は下記リンクをご参照ください。

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

3
Nitin

ファクトリパターンは、インスタンス化ロジックを公開せずにオブジェクトのインスタンス化を扱います。つまり、ファクトリは実際には共通のインターフェースを持つオブジェクトの作成者です。

サブクラスはインスタンス化するクラスを決定できます。

次の例を検討してください。

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
    {

    }
}
2

システムが製品の作成、構成、表現の方法から独立している必要がある場合は、抽象ファクトリパターンを使用します。システムは、複数の製品ファミリの1つで構成する必要があります。関連製品オブジェクトのファミリーは一緒に使用するように設計されており、この制約を適用する必要があります。製品のクラスライブラリを提供する必要があり、実装ではなく、インターフェイスのみを明らかにする必要があります。

2

新しいキーワードではなく、ファクトリメソッドパターンを使用することをお勧めします。アイデアは、オブジェクトの完全なインスタンス化をビジネスロジックの外に移動することです。この原理は 依存性注入 の核心です。また、ファクトリメソッドの作業は、後でSpring.netやCastle WindsorのようなDependency Injection Frameworkに委任できます。

1
abhilash