如何实现一个复杂类型的构建器?

问题描述 投票:0回答:1

我有一个非常复杂的类型。该类型有多个可读属性,每个属性都是一个复杂类型。

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). 然后返回void。现在所有的构建器都有相同的方法签名。这种方法的缺点是,你会受到诱惑,想在 FinalResult 还没有设置的。

我很想听听如何用好的OO方式解决这个问题。

c# design-patterns solid-principles builder-pattern
1个回答
0
投票

你可以使用一个单一的生成器类来构建所有类型。一般的规则(对我来说)是,如果你有很多类,每个类都只有1个方法,那么这是过度设计,你至少应该考虑制造更少的类,甚至是一个拥有所有这些方法的单一类。

现在我们有了一个Builder类,也就变得容易了,可以尝试去掉这些方法。FinalResultDirector 类。

这个+我加了 internal set; 因为除了从构造函数或类内部的初始化器外,你不能赋值readonly属性。

工作代码 + 点网提琴:

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)
        };
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.