Как добавить случайную функцию для фабричного дизайна? - PullRequest
0 голосов
/ 29 января 2012

Я работаю над внутренним проектом для моей компании, и часть проекта должна быть в состоянии генерировать различные "математические проблемы" в заводском дизайне.

  • Чтобы создать проблемы, необходимоукажите уровень сложности на заводе.
  • Каждый ProblemFactory содержит методы тезисов в виде ConfigureXLevels, а Generate.
  • Предоставляет переменную Random.
  • Содержитсловарь, содержащий доступные уровни (key:=Levels, value:=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();
    }
} 

А вот конкретный класс о проблемах создания дополнений, проверьте, как я переопределяю некоторые ConfigureXLevel из абстрактного ProblemFactory и возвращает 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  …
}

Дело в том, что Generate method из AdditionProblemFactory и TimesTablesProblemFactory, x, y должны получать случайные числа согласно Уровню IConfiguration.

Bound класс содержит Min и Max значений.Например, если я выбираю 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

Ответы [ 2 ]

1 голос
/ 29 января 2012

Проведя некоторый рефакторинг, я бы предложил создать следующую иерархию классов:

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);
}

В качестве альтернативы, вы можете предоставить различные IConfiguration объекты в конструкторе для ProblemFactory и иметь разные экземпляры для различных конфигураций.

0 голосов
/ 29 января 2012

Я бы начал с рефакторинга фабричного класса. иметь класс для каждого уровня сложности: 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 вы используете, будет определять способ конфигурирования фабрик.

Другой вариант - заменить фабричные объекты объектами команд и объединить команды в цепочку. например, команда для сложения, вычитания, кратного, деления. затем объедините эти команды в цепочку, чтобы создать проблему. Вы даже можете создавать команды для экспонент, пи, логарифмических функций.

...