我有一个模拟LogicalExpressions的类。叶子是实现接口IEvaluable的类,它有一个名为计算的方法,该方法返回布尔值作为结果。
public class MyEvaluable : IEvaluable
{
public bool Evaluate(Environment env)
{
}
}其中一些可评估对象需要做一些繁重的工作才能产生结果,例如调用web服务。由于一个逻辑表达式可能有多个这样的相关对象,所以我想一次对它们进行评估,为所有这些对象执行一个web服务调用,而不是对每个参数进行单独的调用。
因此,我一直在考虑设计这样一个系统的好方法,并想出了两个解决方案:
1)使我的可评估对象变。
public interface IBatchEvaluable
{
void BatchEvaluate(object[] siblings, Common.Environment env);
bool IsEvaluated { get; }
bool EvaluationResult { get; }
}
public interface IBatchEvaluable<T> : IBatchEvaluable
{
void BatchEvaluate<T>(T[] siblings, Common.Environment env);
}因此,每一个对象,即IBatchEvaluable,都有一个状态。当我需要评估它时,我会检查它是否已经被评估过,如果需要的话进行批评估。唯一的缺点是,我的对象将是可变的,这并不是真正需要的。
2)在环境中存储评估数据
我可以将对象保持不变,并在环境中移动IsEvaluated和EvaluationResult数据。因此,每个对象都会首先在环境中查看它是否已经被评估过,如果是的话,从环境中得到结果,否则就一次评估所有的兄弟姐妹,并将数据放入环境中。
这也不是很有吸引力,因为我的对象的实现将依赖于外部数据,似乎不遵守OOP原则。
我应该如何从面向对象的角度来处理这个问题呢?我愿意听取其他可能的解决办法。
发布于 2017-01-16 15:54:07
由于一个逻辑表达式可能有多个这样的相关对象,所以我想一次对它们进行评估,为所有这些对象执行一个web服务调用,而不是对每个参数进行单独的调用。
那你为什么不这么做呢?
当您调用web服务之类的时候,查看和回忆录表达式的结果并不理想,因为它们总是非纯调用。如果您现在要求温度,web服务将给您一个不同的结果,从现在起一个小时。通过在幕后使用这种批处理方法,您将从用户那里不知不觉地更改计算结果。
如果您的目标是获取所有数据,然后对其进行操作,那么就这样做。简单地说,你描述的是MapReduce。与其在单个项上有逻辑表达式,不如将设计转换为在集合上工作的操作。然后,将数据作为批处理获得并对该批处理执行操作变得更加自然。您不需要太担心是否已经加载了部分数据,因为在set操作世界中它变得更清晰了。使用大量现有的实现,您可以找到可以帮助的资源,或者可能发现根本不需要编写代码,因为它已经存在了。
发布于 2017-01-16 15:37:23
您可以使用的一种方法是使用组合和策略模式。这不会消除易变性,它将解决您在问题末尾指向的对封装的关注。基本上,在您的Evaluable上再添加一个层。它将有一个对另一个Evaluable的引用,它要么是可以解决的,要么是结果。当调用复合Evaulable时,可以从可解析的Evaluable获得结果,并将其放入结果对象中。
如果您想完全不可知,那么您只需使用每个Evaluable就可以做到这一点,而不管它是否已经解决。这将产生大量新对象,但这可能不是一个问题。如果是的话,您可以向Evaluable中添加一个方法,将结果作为Evaluable返回,而解析的结果只返回this。
https://softwareengineering.stackexchange.com/questions/340278
复制相似问题