43

しばらくの間、ファクトリ メソッド作成パターンを使用しています。私はつい最近、次のように言われました。

public static class ScheduleTypeFactory
{
    public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)
    {
        IScheduleItem scheduleItem = null;

        switch (scheduleType)
        {
            case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
                {
                    scheduleItem = new VODScheduleItem();
                    break;
                }
            case ScheduleTypeEnum.BroadbandScheduleTypeID:
                {
                    scheduleItem = new VODScheduleItem();
                    break;
                }
            case ScheduleTypeEnum.LinearCableScheduleTypeID:
                {
                    scheduleItem = new LinearScheduleItem();
                    break;
                }
            case ScheduleTypeEnum.MobileLinearScheduleTypeID:
                {
                    scheduleItem = new LinearScheduleItem();
                    break;
                }
        }

        return scheduleItem;
    }
}

理由を教えたり、解釈を与えたりせずに、私の「テック」リードによるファクトリメソッド作成パターンではありません。私は親切に説明を求めましたが、彼女は時間がないと言いました。改名するように言われました。私が間違っていれば、何年にもわたってこれを間違って実装してきたことを間違いなく受け入れるでしょう。これは、ファクトリ メソッド作成パターンを実装する方法ですか? 前もって感謝します。

4

20 に答える 20

31

設計は厳密には「ファクトリー メソッド パターン」ではありませんが、このメソッドを「ファクトリー メソッド」と呼ぶことに同意します。
キーポイントは次のとおりです(ウィキペディアから):

...Factory メソッドを使用すると、クラスはインスタンス化をサブクラスに任せることができます。"

あなたのクラスは静的でメソッドは静的であるため(したがって非仮想)、「遅延」はありません。

概念的には、この実装はカプセル化を提供しますが、決定を切り離したり遅らせたりしないことに注意してください。

そうは言っても、同じウィキペディアの記事では、このスキーマを「Factory Method Pattern」 の変形として提示しています。

要約の要約: 私の意見では、このスニペットは「ファクトリ メソッド OO デザイン パターン」の適切な実装ではありません。ただし、個人的には、このソリューションを「ファクトリーメソッド」と自由に呼んでいます。

実際ファクトリ メソッド パターンにするには、メソッドをサブクラスでオーバーライドできるようにする必要があります。つまり、ファクトリ クラス (ScheduleTypeFactory) は拡張可能 (つまり非静的) である必要があり、GetScheduleItem は仮想である必要があります。

于 2009-05-01T14:40:53.707 に答える
29

確かに私にはファクトリパターンのように見えます。私はあなたの実装に何も悪いことは見ていません。

ファクトリメソッドパターンから:

ファクトリパターンの本質は、「オブジェクトを作成するためのインターフェイスを定義しますが、インスタンス化するクラスをサブクラスに決定させることです。ファクトリメソッドを使用すると、クラスはサブクラスへのインスタンス化を延期できます。」

これはまさにあなたがしていることです。

補足として、大まかな目安として、誰かがあなたに何かを話し、その発言の根拠を提供できない、または提供したくない場合はいつでも、発言する資格がまったくない可能性があります。

于 2009-04-30T13:32:34.503 に答える
14

はい、これはファクトリパターンです。私の唯一のコメントは、特に処理しない列挙値については黙って失敗するということです。それは予想されるかもしれませんが、私はそのようなステートメントの最後に以下を追加したいと思います

default:
  throw new InvalidOperationException("Invalid Enum Value");
于 2009-04-30T13:34:00.023 に答える
12

コードフラグメントは、Head First DesignPatternsで「TheSimpleFactory」(p.117)と呼ばれるものです。ファクトリメソッドパターン
と の主な違いは、ConcreteCreator(右上隅の図を比較)です。これは、この場合の単純なクラスです。「実際のパターン」では、ファクトリクラスは抽象ファクトリクラスと抽象です。したがって、もう1つの抽象化レベルがあります。ただし、多くのユースケースでは、SimpleFactoryで十分です。

シンプルファクトリ シンプルファクトリhttp://yuml.me/7221a4c9 ファクトリメソッドパターン ファクトリメソッドパターンhttp://yuml.me/3d22eb4e

于 2009-09-13T23:35:38.983 に答える
8

「本物の」 Abstract Factoryパターンと区別するために、伝統的にシンプルファクトリーパターンと呼ばれていると思います。ある種の内部命名慣行を順守していない可能性があります。彼女は本当に自分自身を説明する必要があります。

于 2009-04-30T13:37:51.637 に答える
8

あなたのリードは正しいです (フォーマットについては申し訳ありませんが、この回答は、リードがばかであると述べているメインラインの間に表示されるために、その一部が必要です):GOFブックでもHead Firstでも、これはファクトリメソッドではありません。

GoF :

「オブジェクトを作成するためのインターフェースを定義しますが、インスタンス化するクラスはサブクラスに決定させます。ファクトリ メソッドにより、クラスはインスタンス化をサブクラスに任せることができます。」</p>

あなたの例では、決定しているのはサブクラスではありません

ここ数年、間違って実装していませんか? いいえ、ファクトリ パターンを実装していないだけですが、「単純なファクトリ パターン」と呼ばれることもあり、おそらく問題なく機能しています。

于 2009-12-07T11:36:50.320 に答える
5

私には(基本的な)ファクトリのように見えます...多くのファクトリでは、実装はより複雑です(おそらく、実行時に解決される型が含まれます)が、それは(AFAIK)要件ではありません。私が付け加えた他の唯一の批評は、ケースを組み合わせて、タイプを認識しない場合はもっと劇的なことをすることです...

于 2009-04-30T13:34:07.030 に答える
5

これが工場のパターンだと言う人が多くて驚いています。(私の考えが間違っている可能性が高いので、教えてください。)

あなたが持っているものはデザインの一部に過ぎないように私には見えます。クライアントから呼び出す場合、それは「単純な」ファクトリと呼ばれますが、実際にはデザイン パターンとは見なされません。(誤解しないでください、私はいつもこれをやっています)。

ファクトリ設計パターンは、ファクトリが抽象的なファクトリ/ファクトリ インターフェイスを継承/実装することを示します。

次に、ファクトリ (クライアント) を使用する必要があるクラスで、ファクトリのタイプを抽象/インターフェイスに設定し、具体的なファクトリを作成します。つまり、 --> IFactory factory = new ConcreteFactory();

次に、具象ファクトリが IScheduleItem を作成します (具象型を実際に作成するのはファクトリに任せます)。

最終的には、要点は疎結合に関するものだと思います。「単純な」ファクトリーは製品の構築をクライアントから疎結合しますが、ファクトリーを切り離すわけではありません。factory パターンはまた、factory を切り離します。

私はまだコーヒーを飲んでいないので、質問の要点を完全に理解していない非常に恐ろしい回答を投稿するという厄介な癖があります。

于 2009-05-01T13:05:47.807 に答える
4

さて、ウィキペディアはそれがファクトリメソッドであると言っています:

public class ImageReaderFactory 
{
    public static ImageReader getImageReader( InputStream is ) 
    {
        int imageType = figureOutImageType( is );

        switch( imageType ) 
        {
            case ImageReaderFactory.GIF:
                return new GifReader( is );
            case ImageReaderFactory.JPEG:
                return new JpegReader( is );
            // etc.
        }
    }
}
于 2009-04-30T13:35:25.980 に答える
4

これは Factory パターンですが、必ずしも最もメンテナンスしやすいバリアントではありません。 より保守しやすいバリアントScheduleTypeEnumは、値と実際の具体的なサブタイプの間のある種のグローバル マップを維持します。これにより、ステートメントをマップのルックアップにIScheduleItem置き換えることができます。switch

なぜ保守性が高いのですか? サブクラスの作成者は、ファクトリ関数自体ではなく、クラスを派生させたサイトでペアをマップに追加できるためです。GetScheduleItem()したがって、後者は更新する必要はありません。常に最新です。

C++ では、グローバルを使用してこれを行うことができます。std::map具体的なサブクラスごとに、サブクラスの作成者はダミーのグローバル変数を追加します。この変数は、プログラムの起動時に実行されるコンストラクターに (マップに追加することによって) クラスを実際に登録するだけです。C# で同じことを行う便利な方法があると確信しています。

(C++ の第一人者である Herb Sutter の面白い説明がここにありますが、かなり C++ に重きを置いています。)

于 2009-04-30T14:23:46.783 に答える
2

IScheduleItemある種のロジックに基づいての特定のインスタンスを返すメソッドがあるという点で、これは確かに「ファクトリ」です。ただし、switchステートメントを使用していることを考えると、これはおそらく最良の実装または最も保守しやすいものではありません。

于 2009-04-30T13:34:53.673 に答える
0

うん、それは大丈夫ファクトリパターンです。あなたのテックリードは間違っています。

于 2009-04-30T13:34:30.333 に答える
0

私には基本的なファクトリパターンのように見えます。あなたの技術リーダーがこれがパターンであると思わない理由を知りたいです。

彼女が物事を説明するのに時間がかからなかったのも残念です。以前はチームで技術リーダーを務めていたので、時間をかけて自分の決定を説明することが重要です。

于 2009-04-30T13:36:00.800 に答える
0

少なくともウィキペディアによると、これはファクトリメソッドパターンです:http: //en.wikipedia.org/wiki/Factory_method_pattern

于 2009-04-30T13:36:09.520 に答える
0

あなたの技術者は、メソッドの名前を変更しています。

public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)

メソッドのアクションは、何かを取得することではなく、何かを作成することです。どのscheduleTypeを作成するかをどのように決定しますか?タイプのスイッチではなく、ロジックをカプセル化する必要があるようです。

また、なぜクラスの静的なのですか?どこから使っていますか?

public class ScheduleTypeFactory
{
    public static IScheduleItem createScheduleFrom(ScheduleTypeEnum scheduleType)
    {

        switch (scheduleType)
        {
            case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
            case ScheduleTypeEnum.BroadbandScheduleTypeID:
                 return new VODScheduleItem();
             case ScheduleTypeEnum.LinearCableScheduleTypeID:
             case ScheduleTypeEnum.MobileLinearScheduleTypeID:
                    return new LinearScheduleItem();
        }

       raise InvalidSchedule;
    }
}
于 2010-10-29T04:47:39.213 に答える
0

パターンと実践クラスから学んだファクトリ パターンの最も簡単な説明は、クラスのインスタンスを作成するために別のクラスに依存している場合、ファクトリ パターンを使用しているということです。

もちろん、多くの場合、クラスを抽象化またはインターフェイスにすることによって、間接的なレイヤーを追加したいと考えています。

これは非常に単純化されたビューですが、いずれにせよ、ファクトリ パターンを使用しています。

于 2009-05-01T14:20:34.037 に答える
0

テクニカル リーダーが考えている可能性が高いのは、Factory パターンは同じオブジェクト内のコンストラクターを置き換えることであり、サブクラスを返さないこと、あるいは無関係なオブジェクトからではなくスーパークラスからサブクラスのみを返すことであるということです。それは間違っていますが、おそらくそれが考え方です。

ウィキペディアがあなたのパターンを例としてリストしているという事実は、それが正しくファクトリ パターンであることを示しています。パターンは、共通のソリューションに共通の言語を提供するために定義されたものであるため、ウィキペディアがこれを例として示している場合、それは明らかに共通の言語の一部です。「工場パターン」が抽象的な意味で何であるかについての学術的議論は、パターンの要点を見逃しています。

于 2009-04-30T14:02:50.330 に答える
0

今すぐ力を取り戻せ!文言から「タイプ」を削除するだけです。スケジュールファクトリーFTW. 待ってください、これは「Schedules」または「ScheduleItems」のファクトリですか? スケジュール項目の場合、ファクトリは「ScheduleItemFactory」と呼ばれる必要があります。表現力豊かに!!!

于 2009-04-30T14:23:49.187 に答える
-1

それは教科書工場パターンです。

一部のテキストではこれを Simple Factory Pattern と呼んでいますが、「Simple」が何を意味するかについての基準を見たことがありません。

私の実践では、ファクトリ パターンは、目的のインターフェイスに対応する具象クラスのインテリジェントな作成です。

しかし、メソッドの命名について技術リーダーと争う必要はありません。名前を変更して、あなたの人生を続けてください。

于 2009-04-30T15:11:14.347 に答える