jeudi 7 mai 2020

How to implement a builder for a complex type?

I have a very complex type. The type has multiple readonly properties and each property is a complex type:

public class FinalResult
{
    public ComplexType1 {get;}

    public ComplexType2 {get;}

    public ComplexType3 {get;}

    public ComplexType4 {get;}
}

Because ComplextTypeX is complex I have created a builder for each of them:

public class ComplexType1Builder
{
    public ComplexType1 Build(Dependency dep, OtherDependency otherDep)
    {
        // build / create the complex object

        return complexType1;
    }
}

public class ComplexType2Builder
{
    public ComplexType2 Build(Dependency dep, OtherDependency otherDep)
    {
        // build / create the complex object

        return complexType2;
    }
}

// same for ComplexType3 and ComplexType4

Finally I have FinalResultDirector which ties everything together:

public class FinalResultDirector
{

    private readonly ComplexType1Builder _builder1;
    private readonly ComplexType1Builder _builder2;
    private readonly ComplexType1Builder _builder3;
    private readonly ComplexType1Builder _builder4;

    public FinalResultDirector(
        ComplexType1Builder builder1, 
        ComplexType2Builder builder2, 
        ComplexType3Builder builder3, 
        ComplexType4Builder builder4 )
    {
        _builder1 = builder1;
        _builder2 - builder2;
        _builder3 = builder3;
        _builder4 = builder4;
    }

    public FinalResult Build(Dependency dep, OtherDependency otherDep)
    {
        return new FinalResult
        {
            ComplexType1 => _builder1.Build(dep, otherDep),

            ComplexType2 => _builder2.Build(dep, otherDep),

            ComplexType3 => _builder3.Build(dep, otherDep),

            ComplexType4 => _builder4.Build(dep, otherDep),
        };
    }
}

This works, but my OO heart is crying. I know this can be solved much nicer, cleaner and more SOLID, but I haven't seen the solution.

I've tried using interfaces, but since each builder returns a different type, it doesn't have any additional value.

Another approach I've been thinking about is new up a FinalResult object and have each Build method accept this as a third parameter: public ComplexTypeX Build(Dependency dep, OtherDependency otherDep, FinalResult finalResult). And then return void. Now all the builders have the same method signature. The downside of this approach is that you get tempted to use properties on FinalResult that aren't set yet.

I'd love to hear how to solve this in a nice OO way.

Aucun commentaire:

Enregistrer un commentaire