Как реализовать конструктор сложного типа? - PullRequest
0 голосов
/ 07 мая 2020

У меня очень сложный типаж. Тип имеет несколько свойств только для чтения, и каждое свойство является сложным типом:

public class FinalResult
{
    public ComplexType1 ComplexType1 {get;set;}

    public ComplexType2 ComplexType2 {get;set;}

    public ComplexType3 ComplexType3 {get;set;}

    public ComplexType4 ComplexType4 {get;set;}
}

Поскольку ComplextTypeX является сложным, я создал конструктор для каждого из них:

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

Наконец, я иметь FinalResultDirector, который связывает все вместе:

public class FinalResultDirector
{

    private readonly ComplexType1Builder _builder1;
    private readonly ComplexType2Builder _builder2;
    private readonly ComplexType3Builder _builder3;
    private readonly ComplexType4Builder _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),
        };
    }
}

Это работает, но мое сердце OO плачет. Я знаю, что это может быть решено намного лучше, чище и более SOLID, но я не видел решения.

Я пробовал использовать интерфейсы, но поскольку каждый построитель возвращает другой тип, он не имеет никакого дополнительного значения.

Другой подход, о котором я думал, - это новый FinalResult и пусть каждый метод Build принимает это как третий параметр: public ComplexTypeX Build(Dependency dep, OtherDependency otherDep, FinalResult finalResult). А потом вернуть пустоту. Теперь у всех построителей одинаковая сигнатура метода. Обратной стороной этого подхода является то, что вы испытываете искушение использовать свойства FinalResult, которые еще не установлены.

Мне бы хотелось услышать, как решить эту проблему красивым объектно-ориентированным способом.

1 Ответ

0 голосов
/ 07 мая 2020

Вы можете использовать один класс Builder, который строит все типы. Общее правило (для меня) заключается в том, что если у вас есть много классов, каждый из которых имеет только 1 метод, тогда это переоценено, и вам следует, по крайней мере, подумать о создании меньшего количества классов или даже одного класса со всеми этими методами.

Теперь, когда у нас есть один класс Builder, также становится проще попытаться удалить класс FinalResultDirector.

Это + Я добавил internal set;, потому что вы не можете назначать свойства только для чтения, кроме как из конструктора или из инициализатор внутри класса.

Рабочий код + dotnetfiddle :

using System;

public class Program
{
    public static void Main()
    {
        var director = new FinalResultDirector(new ComplexTypeBuilder());
        var result = director.Build(new Dependency(), new OtherDependency());

        Console.WriteLine(result);
    }
}

public class ComplexType1 {}
public class ComplexType2 {}
public class ComplexType3 {}
public class ComplexType4 {}

public class Dependency {}
public class OtherDependency{}

public class FinalResult
{
    public ComplexType1 ComplexType1 {get; internal set;}
    public ComplexType2 ComplexType2 {get; internal set;}
    public ComplexType3 ComplexType3 {get; internal set;}
    public ComplexType4 ComplexType4 {get; internal set;}
}

public class ComplexTypeBuilder
{
    public ComplexType1 Build1(Dependency dep, OtherDependency otherDep)
    {
        return new ComplexType1();
    }
    public ComplexType2 Build2(Dependency dep, OtherDependency otherDep)
    {
        return new ComplexType2();
    }
    public ComplexType3 Build3(Dependency dep, OtherDependency otherDep)
    {
        return new ComplexType3();
    }
    public ComplexType4 Build4(Dependency dep, OtherDependency otherDep)
    {
        return new ComplexType4();
    }
}

public class FinalResultDirector
{
    private readonly ComplexTypeBuilder _builder;

    public FinalResultDirector(ComplexTypeBuilder builder)
    {
        _builder = builder;
    }

    public FinalResult Build(Dependency dep, OtherDependency otherDep)
    {
        return new FinalResult
        {
            ComplexType1 = _builder.Build1(dep, otherDep),
            ComplexType2 = _builder.Build2(dep, otherDep),
            ComplexType3 = _builder.Build3(dep, otherDep),
            ComplexType4 = _builder.Build4(dep, otherDep)
        };
    }
}
...