2

ソフトウェアの一部をリファクタリングして、よりテスト可能/DI フレンドリーにし、より拡張可能にしようとしています。元のコードは継承に依存していましたが、コンポーネントのエンド ユーザーが作成中のレイヤーの下にレイヤーを挿入できるようにしたいので、デコレータの方がより柔軟な設計になると考えていました。

thisただし、基本クラスのコードの一部がメソッドの一部に渡されるため、壁にぶつかりました。継承を使用してもthis、最上位のレイヤー タイプを参照するため、これは問題になりませんが、デコレータでこれを機能させる方法を考え出すのに苦労しています。次に例を示します。

public interface INode
{
    bool IsReadOnly { get; }
    void DoSomething();
}

public class Node : INode
{
    public Node(ISomeFactory someFactory)
    {
        if (someFactory == null)
            throw new ArgumentNullException("someFactory");
        this.someFactory = someFactory;
    }

    private readonly ISomeFactory someFactory;


    public bool IsReadOnly { get { return false; } }

    public void DoSomething()
    {
        // Some implementation code here

        // This factory doesn't get an instance of the decorator type
        // when it is in use - this is a problem
        var someInstance = someFactory.Create(this);

        // More code here...
    }
}

public class LockableNode : INode
{
    public LockableNode(INode node, ILockingService lockingService)
    {
        if (node == null)
            throw new ArgumentNullException("node");
        if (lockingService == null)
            throw new ArgumentNullException("lockingService");

        this.innerNode = node;
        this.lockingService = lockingService
    }

    private readonly INode innerNode;
    private readonly ILockingService lockingService;

    public bool IsReadOnly { get { return lockingService.IsReadOnly; } }

    public void DoSomething()
    {
       if (this.IsReadOnly)
           throw new InvalidOperationException("Node is read-only");

       this.innerNode.DoSomething();
    }
}

次に、私の工場は次のようにします。

var someFactory = new SomeConcreteFactory();
var lockingService = new LockingService();

var node = new Node(someFactory);
var lockableNode = new LockableNode(node, lockingService);
return lockableNode;

私のコメントで概説されている問題は、装飾しようとしているコード内のいくつかの場所、現在のオブジェクトがパラメーターとして他のメソッドに渡されており、デコレーターオブジェクトが使用されているときにデコレーターオブジェクトのインスタンスが必要であり、現在のそうでない場合はオブジェクト。デコレータ クラスのファクトリに渡されるコードを再実装するthis以外に、これを修正するためにできることはありますか?

4

2 に答える 2

0

結論として、私の場合、答えは継承を使用することでした。デコレータ パターンはどこかで使用されていると確信していますが、特にいつ、どのように制御できない場合は、クロスメンバー呼び出しを行い、それ自体への参照を他のオブジェクトに渡すドメイン オブジェクトに機能を追加することはそうではありません。将来、他の参照またはクロスメンバー呼び出しがコードに挿入されます。

私が試していないアイデアがいくつかあるこの他の投稿を見つけました。

デコレータのデザインパターンを使用する際の問題

于 2013-02-21T08:37:48.213 に答える
0

doSomething装飾されたオブジェクトをパラメーターとして必要とする実際のメソッドを作成します。

ノード

public void DoSomething()
{
    this.DoSomethingWith(this)
}
public void DoSomethingWith(INode it)
{
    // ...

    var someInstance = someFactory.Create(it);

    // ...
}

LockableNode

public void DoSomething()
{
    this.innerNode.DoSomethingWith(this);
}
public void DoSomethingWith(INode it)
{
    this.innerNode.DoSomethingWith(it);
}

編集:もちろん、インターフェイスも変更する必要があります。

public interface INode
{
    bool IsReadOnly { get; }
    void DoSomething();
    void DoSomethingWith(INode it);
}
于 2013-02-13T11:31:19.710 に答える