我有一个非常复杂的类型。该类型有多个可读属性,每个属性都是一个复杂类型。
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方式解决这个问题。
你可以使用一个单一的生成器类来构建所有类型。一般的规则(对我来说)是,如果你有很多类,每个类都只有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)
};
}
}