2

更新私の問題をよりよく説明するために、例を更新しました。特定のポイントが 1 つ欠けていることに気付きました。つまり、CreateLabel()メソッドは常にラベル タイプを使用するため、ファクトリが作成するラベルのタイプを決定できるという事実です。つまり、返すラベルのタイプに応じて、多かれ少なかれ情報を取得する必要がある場合があります。

プリンターに送信されるラベルを表すオブジェクトを返すファクトリ クラスがあります。

ファクトリ クラスは次のようになります。

public class LargeLabel : ILabel
{
    public string TrackingReference { get; private set; }

    public LargeLabel(string trackingReference)
    {
        TrackingReference = trackingReference;
    }
}

public class SmallLabel : ILabel
{
    public string TrackingReference { get; private set; }

    public SmallLabel(string trackingReference)
    {
        TrackingReference = trackingReference;
    }
}

public class LabelFactory
{
    public ILabel CreateLabel(LabelType labelType, string trackingReference)
    {
        switch (labelType)
        {
            case LabelType.Small:
                return new SmallLabel(trackingReference);
            case LabelType.Large:
                return new LargeLabel(trackingReference);
        }
    }
}

CustomLabel という名前の新しいラベル タイプを作成するとします。これを工場から返却したいのですが、追加のデータが必要です:

public class CustomLabel : ILabel
{
    public string TrackingReference { get; private set; }
    public string CustomText { get; private set; }

    public CustomLabel(string trackingReference, string customText)
    {
        TrackingReference = trackingReference;
        CustomText = customText;
    }
}

これは、ファクトリ メソッドを変更する必要があることを意味します。

public class LabelFactory
{
    public ILabel CreateLabel(LabelType labelType, string trackingReference, string customText)
    {
        switch (labelType)
        {
            case LabelType.Small:
                return new SmallLabel(trackingReference);
            case LabelType.Large:
                return new LargeLabel(trackingReference);
            case LabelType.Custom:
                return new CustomLabel(trackingReference, customText);
        }
    }
}

ファクトリは最小公分母に対応する必要があるため、私はこれが好きではありませんが、同時に CustomLabel クラスはカスタム テキスト値を取得する必要があります。追加のファクトリ メソッドをオーバーライドとして提供することもできますが、CustomLabel には値が必要であるという事実を強制したいと考えています。そうしないと、空の文字列しか与えられません。

このシナリオを実装する正しい方法は何ですか?

4

8 に答える 8

4

さて、ファクトリ メソッドをどのように呼び出しますか?

API をどのように使用できるようにするかに集中すると、通常、実装自体がかなり明確になります。API の目的の結果を単体テストとして記述すれば、これはさらに簡単になります。

ここでオーバーロードを行うのは正しいことかもしれませんが、実際にはファクトリをどのように使用するかによって異なります。

于 2009-03-30T16:45:28.480 に答える
1

構成クラスを使用して、そのインスタンスをファクトリに渡すようにしてください。構成クラスは階層を構築し、ファクトリから期待される結果ごとに特別な構成クラスが存在します。各構成クラスは、ファクトリ結果の特定のプロパティをキャプチャします。

あなたが与えた例のために、私はBasicLabelConfigurationとそれから派生したCustomLabelConfigurationを書きます。BasicLabelConfigurationは追跡参照をキャプチャし、CustomLabelConfigurationはカスタムテキストをキャプチャします。

最後に、ファクトリは渡された構成オブジェクトのタイプに基づいて決定を下します。


コードの例を次に示します。

public class BasicLabelConfiguration
{
  public BasicLabelConfiguration()
  {
  }

  public string TrackingReference { get; set; }
}

public class CustomLabelConfiguration : BasicLabelConfiguration
{
  public CustomLabelConfiguration()
  {
  }

  public string CustomText { get; set; }
}

public class LabelFactory
{
  public ILabel CreateLabel(BasicLabelConfiguration configuration)
  {
    // Possibly make decision from configuration
    CustomLabelConfiguration clc = configuration as CustomLabelConfiguration;
    if (clc != null)
    {
      return new CustomLabel(clc.TrackingReference, clc.CustomText);
    }
    else
    {
      return new BasicLabel(configuration.TrackingReference);
    }
  }
}

最後に、次のようにファクトリを使用します。

// Create basic label
ILabel label = factory.CreateLabel(new BasicLabelConfiguration 
{
  TrackingReference = "the reference"
});

また

// Create basic label
ILabel label = factory.CreateLabel(new CustomLabelConfiguration 
{
  TrackingReference = "the reference",
  CustomText = "The custom text"
});
于 2009-03-30T16:45:49.510 に答える
1

これはおそらく、ファクトリ パターンが最適ではないことを示しています。ただし、それが必要な場合、またはそれに固執したい場合は、文字列ではなく、ファクトリに渡すことができる初期化クラス/構造体を作成することをお勧めします。基本情報クラスのさまざまなサブクラス (基本的には、ラベル クラスの階層を模倣する初期化クラス階層を作成する) を使用するか、すべての情報を含む 1 つのクラスを使用するかは、ユーザー次第です。

于 2009-03-30T16:44:37.640 に答える
1

詳細な情報がなければ、アドバイスを与えるのはかなり難しいですが、ファクトリ パターンが実際に必要なものであると仮定すると、次のアプローチを試すことができます。

必要な引数をある種のプロパティ マップ (文字列から文字列へのマップなど) にパックし、それを引数としてファクトリの create メソッドに渡します。よく知られたタグをマップのキーとして使用して、特殊なファクトリがマップされた値を自分の好みに合わせて抽出および解釈できるようにします。

これにより、少なくとも当面は単一のファクトリ インターフェイスを維持し、ファクトリ パターンがここで正しいものではないことに気付いた場合 (またはそのとき) にアーキテクチャの問題への対処を延期することができます。

(ああ、ここでファクトリ パターンを本当に使用したい場合は、新しいラベル タイプごとにファクトリを変更する必要がないように、プラグイン可能にすることを強くお勧めします)。

于 2009-03-30T17:27:50.250 に答える
1

パターンが適合しないシナリオにパターンを強制しようとしています。最も単純な解決策を可能にするのではなく、その特定のパターンと焦点をあきらめることをお勧めします。

この場合、通常は null/空ですが、ラベルをカスタムにする必要がある場合に設定できるカスタム テキスト用のテキスト フィールドを持つ Label クラスを 1 つだけ持つと思います。シンプルで一目瞭然で、保守プログラマーに悪夢を与えることはありません。

public class Label
{
    public Label(string trackingReference) : this(trackingReference, string.Empty)
    {
    }

    public Label(string trackingReference, string customText)
    {
        CustomText = customText;
    }

    public string CustomText ( get; private set; }

    public bool IsCustom
    {
        get
        {
            return !string.IsNullOrEmpty(CustomText);
        }
    }
}
于 2009-03-30T17:55:14.070 に答える
0

質問を読むと、UI が情報を収集し、ファクトリを使用して適切なラベルを作成するように思えます。私が開発する CAD/CAM アプリケーションでは、別のアプローチを使用しています。

アプリケーションの起動時に、ファクトリ メソッドを使用してラベルのマスター リストを作成します。一部のラベルには初期化パラメーターがあります。これは、それらが互いにバリアントであるためです。たとえば、3 種類のフラット パーツ ラベルがあります。他のものには、ユーザー定義のパラメーターまたはセットアップ時に不明なパラメーターがあります。

最初のケースでは、初期化はファクトリ メソッド内で処理されます。そこで、必要なパラメーターを渡す FlatPartLabel の 3 つのインスタンスを作成します。

2 番目のケースでは、ラベル インターフェイスに構成オプションがあります。これは、ラベル プリンター ダイアログによって呼び出され、セットアップ パネルに入力されます。あなたの場合、これは追跡参照と CustomText が渡される場所です。

私のラベル インターフェイスは、ラベル タイプごとに一意の ID も返します。そのタイプのラベルを処理する特定のコマンドがある場合は、アプリケーション内のラベルのリストを走査して ID に一致するものを見つけ、それを特定のタイプのラベルにキャストしてから構成します。これは、ユーザーが特定のフラット パーツに対してのみ 1 つのラベルを印刷したい場合に行います。

これを行うと、ラベルが必要とするパラメーターを任意に複雑にすることができ、重要でないパラメーターで Factory に負担をかけることがなくなります。

于 2009-03-30T19:10:53.780 に答える