Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creation of Builders in Builder Pattern

I want to clarify my use of the builder pattern, in particular how the type of builder is created. In examples, it just assumes the type of builder and creates it. However, I created a CreateBuilder method in a 'ChartBuilderFactory' class which returns the type of builder based on some object that was passed to it. Is this the best way of doing this? I've posted my sample code and would appreciate alternatives and suggestions for better design.

class Program
{
    static void Main(string[] args)
    {
        DataObject data = new DataObject("basic", 2);

        ChartDirector director = new ChartDirector();
        ChartBuilderFactory builderFactory = new ChartBuilderFactory();
        ChartBuilder builder = builderFactory.CreateChartBuilder(data);
        director.Construct(builder);

        Console.WriteLine(builder.GetChart());
        Console.ReadKey();
    }
}

class ChartBuilderFactory
{
    public ChartBuilder CreateChartBuilder(DataObject data)
    {
        ChartBuilder builder;
        if (data.DataType == "basic")
            builder = new ChartBuilderBasic(data);
        else if (data.DataType == "vector")
            builder = new ChartBuilderVector(data);
        else
            builder = null;

        return builder;
    }
}           

class ChartDirector
{

    public void Construct(ChartBuilder builder)
    {
        builder.CreateChart();
        builder.LoadData();
    }
}

abstract class ChartBuilder
{
    protected string myChartObject = "";
    protected DataObject data;

    public ChartBuilder(DataObject data)
    {
        this.data = data;
    }

    abstract public void CreateChart();
    abstract public void LoadData();
    public string GetChart() { return myChartObject; } 
}

class ChartBuilderBasic : ChartBuilder
{
    public ChartBuilderBasic(DataObject data)
        : base(data) { }

    public override void CreateChart()
    {
        myChartObject = "MyBasicChart";
    }

    public override void LoadData()
    {
        myChartObject += Convert.ToString(data.Data);
    }
}

class ChartBuilderVector : ChartBuilder
{ /** Alternative Implementation here */ }

class DataObject
{
    /** Constructor and private member variables here */
    public string DataType { get { return this.dataType; } }
    public int Data { get { return this.data; } }
}
like image 937
Seth Avatar asked Dec 28 '25 03:12

Seth


1 Answers

I think you actually want is to use the Factory pattern to create the Builder classes. The Director does not create the Builder but has the dependency on them.

Have a look at this site which gives a good insight into patterns and uses some real example.

[EDIT : based on revised question]

Now that you have the creating of the Builders inside a factory you are set to go. If you want to remove the condition / finding of the correct builder there are a number of options depending on the size and complexity of the system.

  1. Leave it the way you have it if the number of types of builder and data types will not change (or much at all)
  2. Have a mapping between the builder and type through a dictionary. (more complex) see below
  3. Or completely drive it through configuration by reading a file that maps between the type of data to the type of builder. (going a bit overboard but possible)

The last 2 options might involve reflection (using the Activator class) in order to create the Builder class (or some Dependency Injection containers such as unity), but the exact mechanics are at least encapsulated inside the ChartBuilderFactory

Ideally if you use Dependency Injection (Inversion of Control) you are separating the construction of the objects from the way they are used. And if you centralize this it becomes easier to control and even change later if you need to. Not to mention making it easier to test.

like image 77
aqwert Avatar answered Dec 30 '25 19:12

aqwert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!