2012-03-24 50 views
0

肯定这不是最好的标题。我正在创建一个系统来产生数学问题。开发人员必须实现两个接口:如何维持两个班级之间的沟通?

  • Problem:这包含需要生成问题的属性。
  • Configuration:这是生成Problem的范围参数。

这些接口:

public abstract class Problem 
{ 
} 

public abstract class Configuration 
{ 
} 

enter image description here

这里是为BinaryProblem一个例子。

public class BinaryProblem : Problem 
{ 
    public decimal X { get; set; } 
    public decimal Y { get; set; } 

    public BinaryProblem(decimal x, decimal y) 
    { 
     this.X = x; // Number 1 
     this.Y = y; // Number 2 
    } 
} 

public class BinaryProblemConfiguration : Configuration 
{ 
    // Range for X 
    public int XMin { get; set; } 
    public int XMax { get; set; } 

    // Range for Y 
    public int YMin { get; set; } 
    public int YMax { get; set; } 

    public BinaryProblemConfiguration() { } 
} 

你能看到问题与配置之间的界限吗?我需要放置许多实现这两个接口的模块。

所以,我需要一种方法来生成它们。我想在创建一个抽象类,其中包含:

  • protected static Random:几乎所有的配置需要一个随机的类来创建数字(即random.Next(X1, Y1);)。而且必须是静态的,因为需要始终使用相同的种子创建数字。
  • public abstract TProblem Generate(TConfiguration config); // where : TProblem : Problem, new(), TConfiguration : Configuration

和实施的每个问题类型这个抽象类。

我的问题是:这是一个开始解决这个解决方案的好方法,还是我必须做的其他解决方案?

编辑:我试图一个例子是:

这是我的抽象类,我的意思是我的想法是,当你实例化这个类,您所指定的通用值:

public interface IProblemFactory 
{ 
    Problem CreateProblem(); 
} 

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

    public ProblemBaseFactory(TConfiguration config) 
    { 
     _config = config; 

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

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

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

    public abstract TProblem CreateProblem(TConfiguration config); 
} 

public class BinaryProblemFactory : ProblemBaseFactory<BinaryProblem, BinaryProblemConfiguration> 
{ 
    public override BinaryProblem CreateProblem(BinaryProblemConfiguration config) 
    { 
     var x = GenerateValueInRange(_config.Range1); 
     var y = GenerateValueInRange(_config.Range2); 
     return new BinaryProblem(x, y, Operators.Addition); 
    } 

    private decimal GenerateValueInRange(Range<int> range) 
    { 
     return _random.Next(range.MinValue, range.MaxValue); 
    } 
} 
+0

Sorr,我不明白如何从'问题'和'配置'派生的类应该使用。你可以添加一个使用的例子吗? – MiMo 2012-03-24 00:51:50

+0

为什么X,X1和Y1的范围以及Y,X2,Y2的范围。 Yech!使用XMin和XMax等。 – 2012-03-24 01:19:03

+0

我已添加新信息:) – 2012-03-24 17:15:11

回答

2

我认为这是很好的合起来使用聚合值。在你的案例对象范围将是有用的。喜欢的东西(无需验资分钟< =最大值):

public class Range<T> 
{ 
    public Range(T min, T max)   
    { 
     Min = min; 
     Max = max; 
    } 

    public T Min { get; private set; } 
    public T Max { get; private set; } 
} 

是BinaryProblemConfiguration后看起来就像这样:

public class BinaryProblemConfiguration 
{ 
    public Range<int> XRange { get; set; } 
    public Range<int> YRange { get; set; } 
} 

你真正实施是制品厂。所以我中介不是很具描述性的名字吧:

public interface IProblemFactory 
{ 
    Problem CreateProblem(); 
} 

为每种产品类型创建工厂。每个工厂都知道它创建什么类型的产品以及它需要什么类型的配置。 E.g:

public class BinaryProblemFactory : IProblemFactory 
{ 
    private BinaryProblemConfiguration _config; 
    private Random _random; 

    public BinaryProblemFactory(BinaryProblemConfiguration config) 
    { 
     _config = config; 
     // or you can use const seed here 
     _random = new Random(DateTime.Now.Millisecond); 
    } 

    public override Problem CreateProblem() 
    { 
     var x = GenerateValueInRange(_config.XRange); 
     var y = GenerateValueInRange(_config.YRange); 
     return new BinaryProblem(x, y); 
    } 

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

厂创建:

BinaryProblemConfiguration config = new BinaryProblemConfiguration(); 
config.XRange = new Range<int>(0, 100); 
config.YRange = new Range<int>(-50, 50); 

IProblemFactory problemFactory = new BinaryProblemFactory(config); 

通创建问题工厂某处为IProblemFactory:

Problem problem = problemFactory.CreateProblem(); 

也有没有特别需要的配置对象。我认为产品的创造者应该知道如何创造产品。所以我宁愿去与属性XRange和YRange添加到工厂:

BinaryProblemFactory binaryProblemFactory = new BinaryProblemFactory(); 
binaryProblemFactory.XRange = new Range<int>(0, 100); 
binaryProblemFactory.YRange = new Range<int>(-50, 50); 
+0

是的,这就是我要的!工厂模式。只是一个愚蠢的怀疑,我真的需要我所有的工厂都实现Random属性的同一个实例。如果将此接口转换为Random属性的基类(抽象),是否有任何不便之处? – 2012-03-26 05:07:34

+0

当然,只需创建带有受保护随机字段的抽象ProductFactory即可。如果所有具体的工厂都需要它,您也可以将方法GenerateNewValueInRange移动到抽象工厂。 – 2012-03-26 05:42:07

+0

感谢您的建议。我已更新帖子并设置为最终的当前设计。我想告诉你,因为我觉得非常舒适..也许我没有遵循指导原则,或者在我的IFactory和FactoryBase类中不能理解。你觉得怎么样? – 2012-03-27 19:16:52

0

如果我理解你的问题,我不太确定,但我会试着就此提出我的看法。希望能帮助到你。

我相信你选择了错误的方法。 - 你有两个类,但它们根本就不通信(尽管它们应该是) - 是的,你已经创建了抽象类来派生,但在这种情况下我没有看到原因。他们没有定义任何东西,他们不强制任何逻辑来派生类。当你创建一个接口时,你需要一个从它派生出来的人来实现它。你不能真正实现一个空的类/接口。

首先,我建议解决这个问题。创建需要特定方法或属性的接口,以实现它们。这样,您应该能够更轻松地开发主应用程序,因为您会知道,无论其他开发人员创建什么问题,他都需要使用您可以使用的某些方法来实现您的界面。如果你允许实现一个空的界面,你不能确定,结果会是什么,以及期待什么。你不能依靠他们表现得很好(或者至少你不应该)。其次,不知道你是否知道它,但是当你使用模块(Problem + Config作为一个模块)时,把它们放在一个单独的.cs文件中。这样,您可以拥有几乎无限的数量,并且仍然能够轻松维护您的应用。

第三,我会使用一些接口这样的建议,这些类之间有一定的关系(通信):

public interface IProblem 
{ 
    IProblemConfiguration Config; 

    // other needed methods or properties 
}