4

ファクトリ パターンを使用している場合、実行時にどのように依存関係をコンストラクターに注入しますか?

boolean、array、freetext、matrix など、さまざまな形式で Foos を作成しています。Foo のさまざまな用途が見つかると、その形式のリストが増えていきます。これが私の基本的なコア ドメインです。

public interface IFoo
{
    FooFormat Format { get; }
}

public class Foo : IFoo
{
    private FooFormat _format;

    internal Foo(FooFormat format)
    {
        _format = format;
    }

    public FooFormat Format { get { return _format; } }
}


public abstract class FooFormat
{
}

public class DefaultFooFormat : FooFormat
{
}

public class BooleanFooFormat : FooFormat
{
    public IList<bool> Values { get; set; }
}

public class ArrayFooFormat : FooFormat
{
    private IList<string> _values;

    public ArrayFooFormat(IList<string> values)
    {
        _values = values;
    }

    public IList<string> Values { get { return _values; } }
}

IFoo は、コンシューマ コンテキスト用に装飾されています。

public abstract class FooDecorator : IFoo
{
    private IFoo _foo;

    protected FooDecorator(IFoo foo)
    {
        _foo = foo;
    }

    public FooFormat Format
    {
        get { return _foo.Format; }
    }

    protected IFoo foo
    {
        get { return _foo; }
    }
}

コンシューマーに Foo を直接インスタンス化させたくないので、強制的にファクトリーを使用させます。

public abstract class FooFactory
{
    protected IFoo Build<T>()
    {
        FooFormat format = GetFormat<T>();
        return new Foo(format);
    }

    private FooFormat GetFormat<T>()
    {
        if (typeof(T) == typeof(ArrayFooFormat)) return new ArrayFooFormat(new List<string>());
        if (typeof(T) == typeof(BooleanFooFormat)) return new BooleanFooFormat();
        return new DefaultFooFormat();
    }
}

それでも、彼らは特定のコンテキストのために、私の抽象ファクトリーからファクトリーを派生させる必要があります。

私は特に次のように、html コンテキストで foos を構築しています。

public class HtmlFoo : FooDecorator
{
    public HtmlFoo(IFoo foo) : base(foo) { }

    public string ToHtml()
    {
        return "<div>" + this.Format.ToString() + "</div>";
    }
}


public class HtmlFooFactory : FooFactory
{
    public IFoo BuildFoo<T>()
    {
        IFoo foo = Build<T>();
        return new HtmlFoo(foo);
    }
}

public class HtmlFooConsumer
{
    public void DoSomeFoo()
    {
        var factory = new HtmlFooFactory();
        var htmlBooleanFoo = factory.BuildFoo<BooleanFooFormat>();
        var htmlArrayFoo = factory.BuildFoo<ArrayFooFormat>();
    }
}

私の問題は、抽象的な FooFactory にあります。空の値リストを常に ArrayFooFormat に挿入しています。消費者から値リストを渡せるようにしたい。他の FooFormats については、コンシューマーから適切なコンストラクター引数を渡したいと考えています。しかし、私はパブリック API を非常にシンプルに保ちたいと考えています。BuildFoo() に大量のオーバーロードは必要ありません。

では、HtmlFooConsumer.DoSomeFoo() 内から factory.BuildFoo<T>() 呼び出しにカスタム値リストを渡すにはどうすればよいでしょうか? アイデアはありますか、スタックオーバーフローの達人ですか?

4

2 に答える 2

2

おそらく、抽象的な FooFormat が IFooFormat になり、ジェネリック FooFormat がパラメーターを渡す Init メソッドを提供するこれらの行に沿って何かを行うことができます。

次に、Build の 1 つのオーバーロードにより、パラメーターを渡すことができます。

public interface IFooFormat
{
}

public class FooFormat<TValue> : IFooFormat
{
    private TValue _value;

    public void Init(TValue value)
    {
        _value = value;
    }

    public TValue Value
    {
        get { return _value; }
    }
}

public class ArrayFooFormat : FooFormat<IList<string>> { }

public class BooleanFooFormat : FooFormat<bool> { }

public class DefaultFooFormat : IFooFormat { }

public interface IFoo { }

public class Foo : IFoo
{
    private IFooFormat _format;

    internal Foo(IFooFormat format)
    {
        _format = format;
    }

    public IFooFormat Format { get { return _format; } }
}

public class FooFactory
{
    protected IFoo Build<TFormat, TArg>(TArg arg) where TFormat : FooFormat<TArg>, new()
    {
        TFormat format = new TFormat();
        format.Init(arg);
        return new Foo(format);
    }

    protected IFoo Build<TFormat>() where TFormat : IFooFormat, new()
    {
        return new Foo(new TFormat());
    }
}
于 2008-12-17T06:28:25.970 に答える
0

ファクトリは、基本的に静的変数のオブジェクト指向バージョンです。まとめて使うのは避けたいです。クライアントにファクトリの使用を強制する代わりに、単にオブジェクトをコンストラクタに挿入して、ファクトリの必要性を回避することができます。

于 2008-12-18T09:32:35.053 に答える