Как улучшить мой абстрактный шаблон фабрики? - PullRequest
0 голосов
/ 29 марта 2012

У меня действительно нет большого опыта использования шаблонов проектирования.Я думаю, мне нужно использовать Abstract Factory Pattern в моей ситуации.

Я создаю систему для генерирования математических задач.Разработчик должен реализовать два интерфейса:

  • Проблема: содержит свойства, для которых требуется сгенерированная проблема.
  • Конфигурация: это параметры диапазона или условия для создания проблемы.
  • Фабрика: он отвечает за создание новой Задачи.

Что это значит?Это значит, как черный ящик.Для ввода - Configuration, а для вывода - Problem, интерфейс посередине - заводской.

enter image description here

Здесь у меня есть интерфейс и маркерные интерфейсы:

public abstract class Problem { }
public abstract class Configuration { }
public interface IProblemFactory
{
    Problem CreateProblem();
}

Это база для Фабрики, потому что мне нужен класс Random.Все мои классы, которые реализуют этот класс, должны иметь одинаковое начальное число, поэтому у меня есть статическая установка.

public abstract class ProblemBaseFactory<TProblem, TConfiguration> : IProblemFactory
    where TProblem : Problem
    where TConfiguration : Configuration
{
    private const int DEFAULT_SEED = 100;
    protected TConfiguration _config;
    private static Random _random;

    public ProblemBaseFactory() { }
    public ProblemBaseFactory(TConfiguration config)
    {
        _config = config;

        if (_random == null) _random = new Random(DEFAULT_SEED);
    }

    protected TConfiguration Configuration { get { return _config; } }
    protected Random Random { get { return _random; } }

    public void SetSeed()
    {
        _random = new Random(DEFAULT_SEED);
    }

    public Problem CreateProblem()
    {
        return CreateProblem(_config);
    }

    public abstract TProblem CreateProblem(TConfiguration config);
}

Тогда у меня есть реализация всего этого.Например, это модуль для бинарных проблем типа 2+3.

public class BinaryConfiguration : Configuration
{
    public Range<int> Range1 { get; set; }
    public Range<int> Range2 { get; set; }
    public List<Operators> Operators { get; set; }

    public BinaryConfiguration(Range<int> range1, Range<int> range2, List<Operators> operators)
    {
        this.Range1 = range1;
        this.Range2 = range2;
        this.Operators = operators;
    }

public class BinaryProblem : Problem
{
    public BinaryProblem(decimal x, decimal y, Operators op, decimal response)
    {
        this.X = x;
        this.Y = y;
        this.Response = response;
    }

    public decimal X { get; private set; }
    public decimal Y { get; private set; }
    public decimal Response { get; private set; }
}

public enum Operators
{
    Addition, Substract, Multiplication, Division
}

И самая важная часть - это бетонный завод.Посмотрите на эту часть, я установил общие значения.Зачем?Поскольку я предполагал, что это лучший способ реализовать конкретные значения, я имею в виду, что мне не нужно прямо сейчас приводить какие-либо значения.

public class BinaryFactory : ProblemBaseFactory<BinaryProblem, BinaryConfiguration>
{
    public BinaryFactory(BinaryConfiguration config) : base(config) { }

    public override BinaryProblem CreateProblem(BinaryConfiguration config)
    {
        var x = GenerateValueInRange(config.Range1);
        var y = GenerateValueInRange(config.Range2);

        var index = Random.Next(config.Operators.Count);
        var op = config.Operators[index];

        return new BinaryProblem(x, y, op, x + y);
    }

    private decimal GenerateValueInRange(Range<int> range)
    {
        return Random.Next(range.Min, range.Max);
    }
}

И реализовать это:

        BinaryConfiguration configuration = new BinaryConfiguration() {.. }
        IProblemFactory factory = new BinaryFactory(configuration);
        var a = factory.CreateProblem();

Но на данный момент, я думаю, это не лучший дизайн ... потому что, если я хочу использовать новую конфигурацию, я должен создать еще один экземпляр, и я предположил, что это не самая лучшая вещь.

Какя могу улучшить это?

1 Ответ

1 голос
/ 29 марта 2012

В качестве отправной точки я бы предложил использовать рекурсивное определение типа. Попробуйте это:

public abstract class Problem<P, C>
    where P : Problem<P, C>
    where C : Configuration<P, C>
    { }

public abstract class Configuration<P, C>
    where P : Problem<P, C>
    where C : Configuration<P, C>
    { }

public interface IProblemFactory<P, C>
    where P : Problem<P, C>
    where C : Configuration<P, C>
{
    P CreateProblem(C configuration);
}

Это эффективно реализует шаблон «банды четырех» для ваших типов.

Дайте мне знать, если это поможет.

...