- 我们如何实现构建器 Joshua's Effective Java的图案在 C# 中?
下面是我试过的代码,有没有更好的方法呢?
public class NutritionFacts
{
public static NutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer)
{
return new NutritionFacts.Builder(name, servingSize, servingsPerContainer);
}
public sealed class Builder
{
public Builder(String name, int servingSize,
int servingsPerContainer)
{
}
public Builder totalFat(int val) { }
public Builder saturatedFat(int val) { }
public Builder transFat(int val) { }
public Builder cholesterol(int val) { }
//... 15 more setters
public NutritionFacts build()
{
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) { }
protected NutritionFacts() { }
}
我们如何扩展这样的类?做 我们需要编写单独的构建器 每个派生类 上课?
public class MoreNutritionFacts : NutritionFacts { public new static MoreNutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer) { return new MoreNutritionFacts.Builder(name, servingSize, servingsPerContainer); } public new sealed class Builder { public Builder(String name, int servingSize, int servingsPerContainer) {} public Builder totalFat(int val) { } public Builder saturatedFat(int val) { } public Builder transFat(int val) { } public Builder cholesterol(int val) { } //... 15 more setters public Builder newProperty(int val) { } public MoreNutritionFacts build() { return new MoreNutritionFacts(this); } } private MoreNutritionFacts(MoreNutritionFacts.Builder builder) { } }
最佳答案
在 Protocol Buffers 中,我们像这样实现构建器模式(大大简化):
public sealed class SomeMessage
{
public string Name { get; private set; }
public int Age { get; private set; }
// Can only be called in this class and nested types
private SomeMessage() {}
public sealed class Builder
{
private SomeMessage message = new SomeMessage();
public string Name
{
get { return message.Name; }
set { message.Name = value; }
}
public int Age
{
get { return message.Age; }
set { message.Age = value; }
}
public SomeMessage Build()
{
// Check for optional fields etc here
SomeMessage ret = message;
message = null; // Builder is invalid after this
return ret;
}
}
}
这与 EJ2 中的模式不太一样,但是:
- 构建时不需要复制数据。换句话说,当您设置属性时,您是在真实对象上这样做——您只是还看不到它。这类似于
StringBuilder
的作用。 - 构建器在调用
Build()
后失效以保证不变性。不幸的是,这意味着它不能像 EJ2 版本那样用作一种“原型(prototype)”。 - 在大多数情况下,我们使用属性而不是 getter 和 setter - 这非常适合 C# 3 的对象初始值设定项。
- 为了 C#3 之前的用户,我们还提供返回
this
的 setter。
我还没有真正研究过构建器模式的继承——它在 Protocol Buffers 中是不支持的。我怀疑这很棘手。
关于c# - 如何在.net中实现和扩展Joshua的 builder 模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/313729/