0

タイトルはあまり説明的ではないかもしれませんが、私はより良いものを考えることができませんでした。ごめんなさい。

ですから、私がここで抱えている問題は、私が今何度か遭遇した問題です。それは本当にデザインパターンと原則に関するものであり、あなたの言語にOO機能がある限り、言語に依存しません。実際の例なしでは問題が何であるかを説明するのは難しいので、私が抱えている現在の問題について説明します。

したがって、ここではいくつかのクラスを使用してロジックステートメントを記述しています。次のようなことを考えてください。

condition = new And(new Equals("x", 5),
                    new EqualsOrOver("y", 20));

さて、これはすべてダンディですべてですが、このクラスシステムを使用したいときに問題が発生します。現在、条件をSQLWHERE句に変換する必要があるシステムを作成しています。

私はこれをいくつかの方法で行うことができましたが、オープン/クローズの原則に準拠しているものはないようです。たとえば、Databaseクラスに条件を解析させてSQLにすることができます。Condition問題は、このように、変更せずに拡張できないためDatabase、Open/Closedをフォローしていないことです。

別の方法(ここでは論理的に見えるでしょう)はtoSQL()、私のに関数を追加することConditionです。ただし、その場合、データベースを(名前を付けるためだけに)XMLを使用し、SQL形式の条件を必要としないデータベースと交換することはできません。

私が過去にこの問題を回避した1つの方法は、工場を使用することでした。この場合のファクトリメソッドは次のようになります。

turnIntoSQLCondtion(Condition c)
{
    if (c instanceof Equals)
    {
         return new SQLEquals(c);
    }
    else if (c instanceof EqualsOrOver)
    {
         return new SQLEqualsOrOver(c);
    }
    else if (c instanceof And)
    {
         return SQLAnd(c);
    }
}

これはそれほど良いことではありませんが、Open/Closedの違反を減らすことができます。

これで、データベースを適切にサブクラス化できます。ファクトリもサブクラス化する必要があり、同様にCondition固有のクラスの新しい束を作成する必要がありますDatabase。また、Conditionクラスで魔法をかけることもできます。新しいを作成することはできConditionますが、それぞれのコンパニオンクラスも作成する必要がありますDatabase。最後に、工場を変更する必要があります。

これはこれまでに見た中で最小の違反ですが、まだOpen/Closedに違反しています。しかし、実際のところ、私はそれをまったく侵害したくありません。ずっと開いた/閉じたままでこれを行う方法はありますか?

4

3 に答える 3

1

これはそれほど良いことではありませんが、Open/Closedの違反を減らすことができます

実は違う。その方法はOSPの違反です;)

問題はあなたが思うほど難しくはありません。各ConditionクラスをSQL条件クラスにマップするSQLステートメントファクトリを作成するだけです。

    public class SqlFactory
    {
        private Dictionary<Type, Delegate> _factoryMethods
            = new Dictionary<Type, Delegate>();

        public void Assign<T>(Func<T, ISqlCondition> factoryMethod)
            where T : ICondition
        {
            _factoryMethods.Add(typeof (T), factoryMethod);
        }

        public ISqlCondition Create<T>(T source) where T : ICondition
        {
            Delegate factory;
            if (!_factoryMethods.TryGetValue(source.GetType(), out factory))
                return null;

            return ((Func<T, ISqlCondition>) factory)(source);
        }
    }

使用法:

        SqlFactory factory = new SqlFactory();
        factory.Assign<And>(obj => new SqlAnd(obj.Value));

        var and = new And();
        var sqlAnd = factory.Create(and);
于 2011-05-06T12:27:15.430 に答える
0

ここでデコレータパターンによる拡張が役立つかどうか疑問に思っていますか?

述語を一種の DSL、または適切に解析できるルールのリストとして定義する必要があります。

WherePredicate を SqlPredicate として装飾すると、この一連のルールが読み取られ、SQL ステートメントが返されます。XmlPredicate も同様のことを行います。

これにより、オープン/クローズの良い状況になります。新しいデコレータを追加して拡張するためにオープンし、ルールのリストが不可侵であるため、変更のためにクローズします。

于 2011-05-06T12:15:17.143 に答える
0

Protected Variations (PV)は、別のゾーンの変更を必要とせずに、あるゾーンのバリエーションを許可するよう努めています。間接化 (委任) は @jgauffin が提案したものですが、ご指摘のとおり片側のみを保護します。おそらく、さまざまなタイプにデータ駆動型設計 (プロパティ ファイルなど) を使用Storageして、その方向のバリエーションを保護することもできます。あなたの質問を読んだときに、Hibernate とData Mapperについて考えました。

于 2012-04-09T04:48:04.493 に答える