用于生成多个模拟的设计模式是什么?

时间:2016-04-28 19:21:42

标签: design-patterns decorator simulation builder composite

我有一个在特定高度和特定温度下运行的模拟:

interface IGeneratable
{
    string Name { get; }
    void Generate();
}    

interface ISimulation : IGeneratable
{
    int Height { get; }
    int Temperature { get; }        
}

模拟的Generate()过程通常涉及多个步骤:

void Generate()
{
    Step1();
    Step2();
    Step3();
}

现在,用户可以指定多个高度和/或多个温度。

在这种情况下,会产生多个模拟(子模拟),每个高度/温度组合一个。

interface IMultiSimulation : IGeneratable
{
    ISimulation[] SubSimulations { get; }       
}

但是,在这种情况下,子模拟的Generate()方法与Step1,Step2,Step3顺序不同:

  • 如果指定了多个温度,那么Step2()只需要对所有子模拟执行一次,而不是每个温度执行一次(即每次多次模拟一次)。
  • 如果指定了多个高度,则:
      所有子模拟首先预先计算
    • Step1()
    • 然后执行Step2,Step3,..等。
  • 可以进行多个高度和多个温度的宏观模拟。这意味着需要满足上述两个标准。

一般说明

  • 步骤的实现封装在IStep中,实现IGeneratable。因此,模拟可以返回例如步骤列表。
  • 步数可能相当大。

我一直试图使用装饰模式但没有成功。

我正在寻找一个可扩展的解决方案,以处理单个模拟的生成以及多个模拟。

感谢。

4 个答案:

答案 0 :(得分:1)

在您的情况下,我会使用设计模式合成。 generate方法会检查它是否有任何组件。如果没有,它只会调用

void Generate()
{
    Step1();
    Step2();
    Step3();
}

但如果它有组件,则意味着它有多个模拟。然后代码将是:

void Generate()
{
if(this.simulations.Count==0)
{
  Step1();
  Step2();
  Step3();
}
else
 {
    if(multipleHeights)
    {
      precomputeStep1();
      if(multipleHeights)
      {
        createSingletonForStep2(this);
      }
      else
      {
        Step2();
      }
      Step3();
    }
  }
}

对于第2步,我只需要调用一个接收此复合作为参数的单例,因此对于这组模拟,只有一个步骤2.

答案 1 :(得分:1)

接口:

x

典型的MultiSimulation生成:

interface IGeneratable
{
    string Name { get; }
    void Generate();
} 

interface IGeneratableOnce : IGeneratable
{
    bool HasRunned { get; set; }
}   

interface ISimulation : IGeneratable
{
    int Height { get; }
    int Temperature { get; }
    IMultiSimulation MultiSimulation{ get; }
    IGeneratable[] Steps{ get; }

}

interface IMultiSimulation : IGeneratable
{
    ISimulation[] SubSimulations { get; }       
}

典型的ISimulation生成:

void Generate(){
    for (ISimulation simulation in SubSimulations){
        simulation.Generate();
    }
}

ISimulation生成避免第二步运行两次:

void Generate(){
    for (IGeneratable step in Steps){
        step.Generate();
    }
}

如果您愿意,可以添加一些其他标志,甚至可以使用某种方法,如CanRun(int Height,int Temperature),以防您的逻辑过于复杂。 但是在您的情况下,我相信您应该使用像此代码示例的复合模式变体。

编辑:Here您可以使用的另一种有趣模式

答案 2 :(得分:1)

你的任务不是那么小,所以答案不是一个单一的设计模式,而是多个。我个人不会强调模式,而是强调直观和意图揭示的实现(例如我在这里写到:http://www.tutisani.com/software-architecture/intuitive-object-models.html)。我认为你的设计不直观且不能自我描述,所以你不是通过问你所问的问题来解决正确的问题。

无论如何,既然你要求确定设计模式,我也会帮助你。

  • 事实上,所有派生类型(特别是接口)都实现了IGeneratable,即Super Type设计模式。
  • 正如一些人所说,内部包含其他模拟的模拟是Composite模式。但是,由于IMultiSimulation没有实现ISimulation,因此它并不完全准确。无论如何,它是某种复合材料,因为父母和子女都至少实现了IGeneratable。
  • IStep听起来像Strategy模式,但我猜你没有正确实现它。

现在,我想建议您重新考虑一下您的设计方法,因为您的界面不直观。以下是我看到的问题,您需要重新思考:

  • ISimulation具有高度和温度,它还具有Generate()。生成()很可能应该使用高度和温度 - 这就是我理解你的描述的方式,但那时它并不是表达它的正确方法。如果Generate()依赖于Height和Temperature,则将它们作为参数传递,并且不要将它们定义为属性。此外,界面可以更好地表达行为,而不是状态。属性表示状态,我将其表示为类,而不是接口。
  • 如果模拟要执行步骤,不要在ISimulation本身上定义它们 - 这又不是那么直观的设计。将它们作为参数传递,这将使其成为一种策略设计模式(这就是为什么我在上面说过它没有正确实现)。

我会更进一步,但我不知道整个画面。根据您所表达的内容,您提供的实施方式不正确。请重新思考。

答案 3 :(得分:0)

在我看来有一个非常具体的用例来实现,所以我建议使用一个类,包括Generate()的实现(我希望我理解正确的要求)

class Simulation
{
    string Name { get; }
    int[] Heights { get; }
    int[] Temperatures { get; }

    void Generate() {
         for (int i = 0; i < Temperatures.Count; i++) {
             for (int j = 0; j < Heights.Count; j++) {
                  GenerateStep1();
             }
             GenerateStep2();
             GenerateStep3();
         }
    }
}