【问题标题】:How to improve my abstract factory pattern?如何改进我的抽象工厂模式?
【发布时间】:2012-03-29 01:16:48
【问题描述】:

我真的没有太多使用设计模式的经验。我想我需要在我的情况下使用Abstract Factory Pattern

我正在创建一个系统来生成数学问题。开发者必须实现两个接口:

  • 问题:这包含需要生成问题的属性。
  • 配置:这是生成问题的范围参数或条件。
  • 工厂:他负责创建新问题。

这是什么意思?这意味着像一个黑匣子。输入为Configuration,输出为Problem,中间的接口为工厂。

这里有我的界面和标记界面:

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

然后我就有了所有这些的实现。例如,这是一个用于 BinaryProblems 的模块,例如 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();

但是在这一点上,我想这不是最好的设计。因为如果我想使用一个新的配置,我应该创建它的另一个实例,我认为这不是最好的。

我该如何改进它?

【问题讨论】:

  • 讽刺?摆脱抽象和接口。
  • 这可能更适合code review,因为您实际上并没有遇到代码问题。
  • 这与您在 CodeReview 上的问题类似吗? codereview.stackexchange.com/questions/8647/…
  • @RitchMelton 但是我如何获得问题和配置的参考?
  • @dreza 是的,这是这个的旧设计。

标签: c# generics design-patterns factory


【解决方案1】:

作为起点,我建议您使用递归类型定义。试试这个:

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

这有效地为您的类型实现了四人组“桥”设计模式。

如果这有帮助,请告诉我。

【讨论】:

  • 抱歉我的无知,但我应该只使用最后一个,对吧?
  • @DarfZon - 不,你需要全部三个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-15
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
相关资源
最近更新 更多