【问题标题】:Implementing a factory for the Composite pattern为复合模式实现工厂
【发布时间】:2016-08-07 21:39:34
【问题描述】:

我有以下模拟数据:

interface ISimulationData
{
    string Name { get; }
    int[] Heights { get; }
    int[] Temperatures { get; }
}

还有如下接口用于生成:

interface ISimulation
{
    void Generate();
}

使用 Composite 模式来表示单个或多个模拟:

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

interface IMultiSimulation : ISimulation
{
    IEnumerable<ISimulation> GetSimulations();
}

我有以下工厂界面:

interface ISimulationFactory
{
    ISimulation CreateSimulation(ISimulationData simulationData);
}

模拟类型的具体实现:

class SimpleSimulation : ISimpleSimulation
{
    public int Height { get; set; }
    public int Temperature { get; set; }

    public SimpleSimulation(int height, int temperature)
    {
        Height = height;
        Temperature = temperature;
    }

    public void Generate()
    {
        //Height/temperature parameters used here.
    }
} 

abstract class MultiSimulation : IMultiSimulation
{
    public void Generate()
    {
        foreach (ISimulation subSimulation in GetSimulations())
        {
            subSimulation.Generate();
        }
    }

    public abstract IEnumerable<ISimulation> GetSimulations();
}

如果指定了多个高度,则为每个高度生成一个模拟:

class MultiHeightsSimulation : MultiSimulation
{
    private readonly int[] _heights;

    public MultiHeightsSimulation(int[] heights)
    {
        _heights = heights;
    }

    public override IEnumerable<ISimulation> GetSimulations()
    {
        ISimulationFactory factory = new SimulationFactory();

        foreach (int height in _heights)
        {
            //yield return factory.CreateSimulation(???);
        }
    }
}

同样,如果指定了多个温度,则会为每个温度生成一个模拟:

class MultiTemperaturesSimulation : MultiSimulation
{
    private readonly int[] _temperatures;

    public MultiTemperaturesSimulation(int[] temperatures)
    {
        _temperatures = temperatures;
    }

    public override IEnumerable<ISimulation> GetSimulations()
    {
        ISimulationFactory factory = new SimulationFactory();

        foreach (int temperature in _temperatures)
        {
            //yield return factory.CreateSimulation(???)
        }
    }
}    

工厂的具体实现:

class SimulationFactory : ISimulationFactory
{
    public ISimulation CreateSimulation(ISimulationData simulationData)
    {
        if (simulationData.Heights.Length > 1)
        {
            return new MultiHeightsSimulation(simulationData.Heights);
        }

        if (simulationData.Temperatures.Length > 1)
        {
            return new MultiTemperaturesSimulation(simulationData.Temperatures);
        }

        return new SimpleSimulation(simulationData.Heights[0], simulationData.Temperatures[0]);
    }
}

现在我对如何进行以下操作感到困惑:

  • 处理组合的多高度和多温度方案?

我只显示了高度和温度,但还有许多其他参数的行为方式相同,所以我真的在寻找一种合适的解决方案来处理这些多 X 场景,并且耦合最小。

  • ISimulationFactory 只暴露了一种方法,即采用ISimulationData

现在,您可以看到 MultiHeightsSimulationMultiTemperaturesSimulation 正在调用工厂以在特定高度/温度下创建(简单)模拟。目前,工厂没有提供这样的方法,我想知道在工厂中公开这些方法是否有意义?这不会让ISimulationFactory 的客户不知道工厂的实现细节感到困惑吗?

期待听到您的反馈。谢谢!

【问题讨论】:

  • 你描述的情况对我来说就像一个Decorator 用例。我会好好考虑一下并回复你。
  • 我觉得这里有很多过度设计……你觉得所有的复杂性都是必要的吗?
  • 客户是否也想创建 SimpleSimulations?如果没有,你可以让 SimpleSimulation 工厂重载内部吗?

标签: .net design-patterns decorator factory composite


【解决方案1】:

您的模拟工厂已经接受了一个 ISimulationData 参数,其中包含您当前关注的两个变量的数组:

int[] Heights { get; }
int[] Temperatures { get; }

一种选择是让SimulationFactory 为这些数组中的每个元素组合(一种笛卡尔积)生成一个模拟。因此,如果您只有一个高度和 5 个温度,那么您将隐含地拥有您的MultiTemperaturesSimulation。但是,您也可以传入 5 个高度和 4 个温度,在这种情况下,工厂将生成 20 个模拟(每个高度和温度组合一个)...

当您稍后添加这些时,这将很容易适应处理更多维度。因此,您可以有 3 个湿度、4 个高度和 5 个温度,这将导致 3 x 4 x 5 = 60 次模拟。

在这种情况下,您可能需要添加一些代码以确保工厂的 ISimulationData 参数中的每个数组中至少有一个元素(因为如果任何数组的元素为零,那么您结束零模拟 - 这可能没有意义,应该导致ArgumentException)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 2018-08-12
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多