Below is the code I have tried, is there a better way to do this?
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() { }
}
How do we extend such a class? Do we need to write separate builder classes for each of the derived classes?
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) { }
}
The builder pattern, as the name implies, is an alternative way to construct complex objects. This pattern should be used when we want to build different immutable objects using the same object building process. 3.
Builder is a creational design pattern, which allows constructing complex objects step by step. Unlike other creational patterns, Builder doesn't require products to have a common interface. That makes it possible to produce different products using the same construction process.
In Protocol Buffers, we implement the builder pattern like this (vastly simplified):
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;
}
}
}
This isn't quite the same as the pattern in EJ2, but:
StringBuilder
does.Build()
to guarantee immutability. This unfortunately means it can't be used as a sort of "prototype" in the way that the EJ2 version can.this
for the sake of pre-C#3 users.I haven't really looked into inheritance with the builder pattern - it's not supported in Protocol Buffers anyway. I suspect it's quite tricky.
This blog entry might be of interest
A neat variation on the pattern in C# is the use of an implicit cast operator to make the final call to Build() unnecessary:
public class CustomerBuilder
{
......
public static implicit operator Customer( CustomerBuilder builder )
{
return builder.Build();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With