如何提高我的抽象工厂模式? [英] How to improve my abstract factory pattern?

查看:313
本文介绍了如何提高我的抽象工厂模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的没有使用设计模式的经验。我想我需要在我的情况下使用抽象工厂模式



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




  • 问题:包含需要生成问题的属性。

  • 配置:这是产生问题的范围参数或条件。

  • 工厂:他负责创建新的问题。



这是什么意思?这意味着像一个黑盒子。输入是配置,输出是问题,中间的界面是工厂。





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

  public abstract class Problem {} 
public抽象类配置{}
public interface IProblemFactory
{
问题CreateProblem();
}

这是工厂的基础,因为我需要Random类。所有我实施这个的类都必须有相同的种子,所以我有一个静态的实例。

  public abstract class ProblemBaseFactory< TProblem,TConfiguration> :IProblemFactory 
其中TProblem:问题
其中TConfiguration:配置
{
private const int DEFAULT_SEED = 100;
保护TConfiguration _config;
private static Random _random;

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

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

保护TConfiguration配置{get {return _config; }}
protected随机随机{get {return _random; }}

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

public问题CreateProblem()
{
返回CreateProblem(_config);
}

public abstract TProblem CreateProblem(TConfiguration config);
}

然后我有一个所有这一切的实现。例如,这是一个BinaryProblems模块,如 2 + 3

  public class BinaryConfiguration:Configuration 
{
public Range< int> Range1 {get;组; }
public Range< int> Range2 {get;组; }
public List< Operators>运营商{get;组; }

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


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

public decimal X {get;私人集合}
public decimal Y {get;私人集合}
public decimal Response {get;私人集合


public枚举运算符
{
加法,抽象,乘法,除法
}
/ pre>

最重要的部分,这里是一个具体的工厂。看这部分我设置的通用值。为什么?因为我认为是实现具体价值观的最好方式,我的意思是我现在不必投任何价值。

  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];

返回新的BinaryProblem(x,y,op,x + y);
}

私有十进制GenerateValueInRange(范围< int>范围)
{
返回Random.Next(range.Min,range.Max);
}
}

并实现它是:

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

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



如何改进?

解决方案

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

  public abstract class问题< P,C> 
其中P:问题< P,C>
其中C:配置< P,C>
{}

public abstract class Configuration< P,C>
其中P:问题< P,C>
其中C:配置< P,C>
{}

public interface IProblemFactory< P,C>
其中P:问题< P,C>
其中C:配置< P,C>
{
P CreateProblem(C配置);
}

这有效地实现了您的类型的桥设计模式。



让我知道这是否有帮助。


I have really no much experience using design patterns. I guess I need to use Abstract Factory Pattern in my situation.

I'm creating a system to generate math problems. The developer must implement two interfaces:

  • Problem: This contains the properties which needs the problem generated.
  • Configuration: This is the range parameters or conditions to generate a Problem.
  • Factory: He is incharge of create the new Problem.

What does it mean? It means like a black box. For input is the Configuration and the output is Problem, the interface in the middle is the factory.

Here I have my interface and marker interfaces:

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

This is a base for the Factories, because I need the Random class. All my classes which implement this one, must have the same seed, so I have a static instace.

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

Then I have an implementation of all of this. For example, this is an Module for BinaryProblems like 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
}

And the most important part, here is a concrete factory. Look at this part I set the generic values. Why? Because I supposed is the best way to implement the concrete values, I mean I don't have to cast any value right now.

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

And to implement it is:

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

But at this point, I guess this is not the best design.. because if I want to use a new Configuration, I should create another instance of it, and I supposed is not the best thing.

How can I improve it?

解决方案

As a starting point I would suggest that you use a recursive type definition. Try this:

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

This effectively implements the Gang of Four "Bridge" Design Pattern for your types.

Let me know if this helps.

这篇关于如何提高我的抽象工厂模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆