Skip to main content
4 of 4
added 1499 characters in body
Darf Zon
  • 561
  • 3
  • 11

How to add a random feature for a factory design

I'm creating a factory design for math problems. The purpose of the factory is:

  • The problems must be generated with a certain difficulty (or level). To do this, I've got an abstract method called ConfigureLevels.
  • I set an abstract method called Generate, this one must be implemented in a concrete class.

This is the factory design which I'm talking to.

enter image description here

Here is the abstract ProblemFactory.

  • The abstract factory provide a Random variable.
  • Also contains a CanConfigureXLevel() which by default returns false, but if you want that will be available, just override it to true. ConfigureXLevel() is an abstract method which knows how to configure the level (returns IConfigure).
  • Contains a dictionary which contains the available levels (key:=Levels, value:=IConfiguration which works like a container of objects usefull to generate the problem (for example binary and times tables both needs two bound objects)).

_

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

    public virtual bool CanConfigureEasyLevel() { return false; }
    public virtual bool CanConfigureMediumLevel() {return false; }
    public virtual bool CanConfigureHardLevel() {return false; }

    protected abstract IConfiguration ConfigureEasyLevel();
    protected abstract IConfiguration ConfigureMediumLevel();
    protected abstract IConfiguration ConfigureHardLevel();

    private void LoadLevels()
    {
        if (CanConfigureEasyLevel()) {
            Configurations.Add(Levels.Easy, ConfigureEasyLevel());
        }

        if (CanConfigureMediumLevel()) {
            Configurations.Add(Levels.Medium, ConfigureMediumLevel());
        }

        if (CanConfigureHardLevel()) {
            Configurations.Add(Levels.Hard, ConfigureHardLevel());
        }
    }

    private void Configure(Levels level)
    {
        if (!Configurations.ContainsKey(level)) throw new InvalidOperationException("Level not available");

        // ..
    }
} 

And here is a concrete class, check how I'm overriding some ConfigureXLevel from the abstract ProblemFactory. The factory create additions problems, and it should know how to calculates.

public class AdditionProblemFactory : ProblemFactory
{
    public AdditionProblemFactory(Levels level)
        : base(level) { //.. }

    public override Problem Generate(IConfiguration configuration) 
    {
        int x = //.. x must receive a random number according to the configuration
        int y = //..
        Operators op = //..

        return ProblemA.CreateProblemA(x, y, op);
    }

    public override bool CanConfigureMediumLevel()
    {
        return true;
    }

    protected override IConfiguration ConfigureEasyLevel()
    {
        throw new NotImplementedException();
    }

    protected override IConfiguration ConfigureMediumLevel()
    {
        BinaryProblemConfiguration configuration = new BinaryProblemConfiguration();
        configuration.Bound1 = new Bound<int>(2, 10);
        configuration.Bound2 = new Bound<int>(2, 10);
        configuration.Operators = new List<Operators>() { Operators.Addition, Operators.Subtraction, Operators.Multiplication, Operators.Division };

        return configuration;
    }

    protected override IConfiguration ConfigureHardLevel()
    {
        throw new NotImplementedException();
    }
}

And this is a BinaryProblemConfiguration

public class BinaryProblemConfiguration : IConfiguration
{
    public Bound<int> Bound1 { get; set; }
    public Bound<int> Bound2 { get; set; }
    public List<Operators> Operators { get; set; }

    public BinaryProblemConfiguration() { }
    public BinaryProblemConfiguration(Bound<int> bound1, Bound<int> bound2, List<Operators> operators)
    {
        this.Bound1 = bound1;
        this.Bound2 = bound2;
        this.Operators = operators;
    }
}

The matter is in the Generate method from AdditionProblemFactory and TimesTablesProblemFactory, x, y and operator variables should receive random numbers according to the Level IConfiguration.

Here is the part I don't know what I should modify of the design. Maybe is better move the random variable to IConfiguration and generate numbers there.

Here is the current project, don't worry it's so compact (Factories => Infrastructure.FactoryCore | Configurations => Infrastructure.ConfigurationCore | BinaryProblem => ExerciseA):

http://www.mediafire.com/?rf3m1x9b1vdha1k

Darf Zon
  • 561
  • 3
  • 11