【问题标题】:How to add a random feature for a factory design?如何为工厂设计添加随机特征?
【发布时间】:2012-01-29 00:08:38
【问题描述】:

我正在为我的公司开展一个内部项目,该项目的一部分是能够在工厂设计中生成各种“数学问题”。

  • 要产生问题,必须指定工厂的难度级别。
  • 每个ProblemFactory 都包含抽象方法,例如ConfigureXLevels 和Generate
  • 提供Random 变量。
  • 包含一个字典,其中包含可用级别(key:=Levelsvalue:=IConfiguration,其工作方式类似于对生成问题有用的对象容器(例如二进制表和时间表都需要两个 Bound 对象)。李>

_

public abstract class ProblemFactory
{
    private IDictionary<Levels, IConfiguration> Configurations = new Dictionary<Levels, IConfiguration>();
    protected Random Random = new Random();

    public ProblemFactory() {
        LoadLevels();
    }

    protected abstract Problem Generate();
    protected abstract IConfiguration ConfigureEasyLevel();
    protected abstract IConfiguration ConfigureMediumLevel();
    protected abstract IConfiguration ConfigureHardLevel();

    private void LoadLevels() {
            Configurations.Add(Levels.Easy, ConfigureEasyLevel();
            Configurations.Add(Levels.Medium, ConfigureMediumLevel();
            Configurations.Add(Levels.Hard, ConfigureHardLevel();
    }
} 

这是一个关于创建加法问题的具体类,检查我如何从抽象 ProblemFactory 覆盖一些 ConfigureXLevel 并返回IConfiguration

public class AdditionProblemFactory : ProblemFactory
{
    public override Problem Generate() {
        int x = //.. x must receive a random number according to the configuration selected for the level
        int y =  //.. 
        Operators op = Operator.Addition

        return BinaryProblem.CreateProblem(x, y, op);
    }

    protected override IConfiguration ConfigureEasyLevel() {
        // the same of ConfigureMediumLevel() but with others values
    }

    protected override IConfiguration ConfigureMediumLevel() {
        BinaryProblemConfiguration configuration = new BinaryProblemConfiguration();
        configuration.Bound1 = new Bound<int>(100, 1000);
        configuration.Bound2 = new Bound<int>(10, 100);

        return configuration;
    }

    protected override IConfiguration ConfigureHardLevel() {
        // the same of ConfigureMediumLevel() but with others values
    }
}

public class BinaryProblemConfiguration : IConfiguration
{
    public Bound<int> Bound1 { get; set; }  //Bounds for Number1 of a binary problem
    public Bound<int> Bound2 { get; set; } // Bounds…    Number2  …
}

问题在AdditionProblemFactoryTimesTablesProblemFactoryGenerate method中,x, y应该根据Level IConfiguration接收随机数。

Bound 类包含 MinMax 值。比如我选择Levels.Medium,我一定会收到Number1和Number2中特定范围或绑定的问题(Number 1 + Number 2 = X

    AdditionProblemFactory factory = new AdditionProblemFactory();
    BinaryProblem problem = (BinaryProblem)factory.Generate(Levels.Medium);

这是我不知道我应该在设计中修改什么的部分。 Random 在 ProblemFactory 上,但最好将变量移动到 IConfiguration 并在那里生成数字。

如果您喜欢下载它。别担心,它这么小。 http://www.mediafire.com/?z5j9hu1szpuu2u5

【问题讨论】:

  • @L.B 抱歉。我不知道我不应该这样做。我只是想在我的解释中更简短一些。下次我会记住的。

标签: c# design-patterns factory factory-pattern


【解决方案1】:

通过进行一些重构,我建议创建以下类层次结构:

public interface IConfiguration
{
     Bound<int> Bound1 { get; }
     Bound<int> Bound2 { get; }
}

public class EasyLevelConfiguration : IConfiguration
{
    public Bound<int> Bound1
    {
        get { return new Bound<int>(100, 1000); }
    }

    public Bound<int> Bound2
    {
        get { return new Bound<int>(10, 100); }
    }   
}

并按如下方式更改您的 ProblemGeneratorFactory 的实现:

public override Problem Generate(IConfiguration configuration)
{
    int x = this.Random.Next(configuration.Bound1.Max); //use value from configuration
    int y = this.Random.Next(configuration.Bound2.Min); //use value from configuration
    Operators op = Operator.Addition
    return BinaryProblem.CreateProblem(x, y, op);
}

或者,您可以在 ProblemFactory 的构造函数中提供各种 IConfiguration 对象,并为各种配置提供不同的实例。

【讨论】:

  • 在帖子中,IConfiguration 是一个标记接口。其他派生于配置的数学问题有必要产生问题。换句话说,并不是所有的问题都需要两个界限,有些只需要一个,有些需要另一种类型的类,等等。我不确定这是否会影响解决方案
  • @DarfZon,重要的是您尝试将不同的职责彼此分开,并尝试使您的类/接口尽可能精简。如果您有其他需要不同成员或方法的类,那么这些可能应该是一个单独的接口。你可以把上面的IConfiguration接口的名字改成IBinaryProblemConfiguration,比如
  • 我喜欢将枚举级别与类分开的想法。我仍在学习这些设计。对不起,如果我不高兴,你会写下 ProblemFactory 类的内容吗?不知道怎么改。
  • @DarfZon 工厂类和之前一样,只是去掉了Configure*函数,改成Generate的方法签名如上。
【解决方案2】:

我将从重构工厂类开始。每个难度级别都有一个类:EasyProblemFactory、MediumProblemFactory 和 DifficultProblemFactory。允许他们从一个通用接口继承

interface IProblemFactory
{
    Problem Create();
}

那么 ProblemFactory 的每个实现都可以有它自己的特定属性

class EasyProblemFactory
{
    Problem Create()
    {
        return new Problem(...);
    }

    public int X;
    public int Y;
}

class MediumProblemFactory
{
    Problem Create()
    {
        return new Problem(...);
    }

    public Bound<int> Range;
}
...

现在是配置每个工厂的问题,独立于其他类型的工厂,具体取决于工厂的实例化方式以及您使用的 IoC 容器(如果有)将决定您如何配置工厂。

另一种选择是用命令对象替换工厂对象并将命令链接在一起。例如加、减、乘、除的命令。然后将这些命令链接在一起以构建问题。您甚至可以为指数、pi、对数函数创建命令。

【讨论】:

  • 感谢您查看我的代码。我对国际奥委会有疑问,我真的不知道。你能详细解释一下那个容器以及我该如何使用它吗?
猜你喜欢
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 2021-09-09
相关资源
最近更新 更多