2

OCP をコード スニペットに適用しようとしていますが、現在の状態では非常に臭いですが、最後まで到達していないと感じています。

現在のコード:

public abstract class SomeObject
{}

public class SpecificObject1 : SomeObject
{}

public class SpecificObject2 : SomeObject
{}


// Smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    if (someObject is SpecificObject1)
    {}
    else if (someObject is SpecificObject2)
    {}
  }
}

それは本当に醜いです、私の新しいアプローチは次のようになります:

// No so smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    throw new Expception("Not allowed!");
  }

  public void Store(SpecificObject1 someObject)
  {}

  public void Store(SpecificObject2 someObject)
  {}

}

新しい SomeObject 型が登場したら、その特定のオブジェクトを格納する方法を実装する必要があります。これにより、OCP が壊れてしまい、モデル クラスを変更する必要があります。

ストア ロジックを SomeObject に移動するのも間違った原因だと感じているので、SRP に違反します (?)。

Store の実装が欠落している SomeObject の新しい実装が登場すると、Model クラスの Store メソッドで例外が発生し、実行時エラーが発生します。これもコードの匂いのように感じます。

これは、呼び出しコードが次の形式になるためです。

IEnumerable<SomeObject> sequence;

シーケンス オブジェクトの特定の型はわかりません。

OCP の概念を理解できないようです。車/果物の例以上の具体的な例やリンクはありますか?

4

1 に答える 1

1

私が提示しているパターンは、特定のオブジェクトのハンドラーを登録しようとしています。発生する可能性のあるオブジェクトのすべてのタイプに対してハンドラーを登録する必要があります。ハンドラーがそれを処理できなかった場合、例外がスローされます。

ハンドラー ( を実装するすべてのものIHandler) を自分のアセンブリまたは他のアセンブリから動的にロードし、それらをインスタンス化して追加登録することができます。したがって、implements の任意の型のハンドラ クラスを作成するだけで十分SomeObjectです。

public interface IHandler {
    bool TryHandle (SomeObject o); // return true iff handled
}

public class Model
{
    private List<SIandler> _Handlers = new List<IHandlers>();

    // registers a new handler
    public void RegisterHandler (IHandler h) {
        _Handlers.Add(h);
    }

    // this tries to store an object by letting all handlers attempts to store
    public void Store (SomeObject o) {
        foreach (var h in _Handlers) {
            if (h.Store(o)) return;
        }

        // no handler was able to handle the type
        throw new Exception();
    }
}

public class Specific1Handler: IHandler
{
    public bool Handle (SomeObject o) {
        if (o is SpecificType1) {
            /* store... */
            return true; // we handled this object
        } else {
            // we're not qualified
            return false;
        }
    }
}

これはあなたのニーズに合うと思います。(ちなみに、このパターンに名前があるかどうかはわかりませんが、あれば教えていただければ幸いです。)

于 2010-04-22T13:21:39.833 に答える