标题可能不太具描述性,但我想不出更好的标题。对不起,我很抱歉。
所以,我在这里遇到的问题是我现在遇到的问题。它实际上是关于设计模式和原则,并且只要您拥有您所用语言的OO设施,它就是独立于语言的。我将带您了解我遇到的当前问题,因为如果没有实际的例子,很难解释问题是什么。
所以,我在这里使用一些类来描述逻辑语句。想想这样的事情:
condition = new And(new Equals("x", 5),
new EqualsOrOver("y", 20));
现在这一切都很花花公子,但是当我想要使用这个类系统时问题就来了。现在,我正在创建一个系统,其中条件需要转换为SQL WHERE子句。
我可以通过多种方式做到这一点,但似乎没有人遵守开放/封闭原则。例如,我可以让Database
类解析条件并使其成为SQL。问题在于,通过这种方式,我无法在不需要更改Condition
的情况下扩展Database
,因此我们不会关闭打开/关闭。
另一种方式 - 在这里看似合乎逻辑 - 是向toSQL()
添加Condition
函数。但是,在这种情况下,我无法将我的数据库交换为(只是为了命名)使用XML,而不希望SQL格式的条件。
过去我解决这个问题的一种方法是使用工厂。在这种情况下,工厂方法看起来像这样:
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
创建伴随类。最后,您将不得不修改您的工厂。
这是我们迄今为止看到的最小违规行为,但我们仍然违反了开放/封闭。但事实上,我宁愿不要违反它。有没有办法在坚持打开/关闭的同时一直这样做?
答案 0 :(得分:1)
这不是那么好,但它会减少违反Open / Closed
其实没有。该方法违反了OSP;)
问题并不像你想象的那么难。简单地创建一个SQL语句工厂,将每个Condition类映射到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);
答案 1 :(得分:0)
我想知道Decorator模式的某些扩展是否在这里有用?
您希望将谓词定义为一种DSL,或者可以正确解析的规则列表。
如果你将WherePredicate装饰为SqlPredicate,那么它会读取这组规则并返回一个SQL语句;一个XmlPredicate会做类似的事情。
这将使您处于一个良好的开放/关闭状态,通过添加新的装饰器来打开以扩展,并且因为您的规则列表不可侵犯而关闭以进行修改。
答案 2 :(得分:0)
Protected Variations (PV)努力允许在一个区域中进行变化,而无需在另一个区域进行修改。间接(委托)是@jgauffin提出的,但它只会在你指出的时候保护一方。也许您也可以使用不同Storage
类型的数据驱动设计(例如,属性文件)来保护该方向的变化。在阅读你的问题时,我想到了Hibernate和Data Mapper。