# Fluent Builder
---
### A simple example
```csharp
var fruitBasket = ABasketOfFruits()
.WithApples(
new GrannySmith(),
new PinkLady(),
new GoldenDelicious())
.WithBananas(new Banana(), new Banana(), new Banana())
.WithGrapes(new Grapes())
.Create();
```
---
### Basic Builder
- Creational Pattern (see GoF book)
- helps to create complex objects
- helps to separate complex creational logic
- avoids to expose internals of complex objects to the user
---
### Fluent Builder
- build steps are chainable with `.` operator
- helps to create a Domain Specific Language (DSL)
---
### Idea
- accumulate parts of the complex object within an intermediate object (the actual builder)
- use separate `Build()` step to actually create the final object
- builder can be pushed around to collect the several parts
---
### Our Fruits
```csharp
public record Fruit {}
public record Apple : Fruit {}
public record GrannySmith : Apple {}
public record GoldenDelicious : Apple {}
public record PinkLady : Apple {}
public record Banana : Fruit {}
public record Grapes : Fruit {}
```
---
### Full example (classic builder)
```csharp
new class FruitBasketBuilder
{
private List<Apple> Apples { get; } = new List<Apple>();
private List<Banana> Bananas { get; } = new List<Banana>();
private Grapes? Grapes { get; set; }
public static FruitBasketBuilder ABasketOfFruits() => new FruitBasketBuilder();
public void WithApples(params Apple[] apples) => Apples.AddRange(apples);
public void WithBananas(params Banana[] bananas) => Bananas.AddRange(bananas);
public void WithGrapes(Grapes grapes) => Grapes = grapes;
public FruitBasket Create()
{
var fruits = Apples.Cast<Fruit>().Concat(Bananas).ToList();
if(Grapes is not null)
fruits.Add(Grapes);
return new FruitBasket(fruits);
}
}
```
---
### Static Factory Method
Advantages over constructor:
- can be named freely (and expressively)
- multiple methods possible, also with same signature, but different behavior
```csharp
new class FruitBasketBuilder
{
// ...
public static FruitBasketBuilder ABasketOfFruits() => new FruitBasketBuilder();
// ...
}
```
---
### Accumulating Parts
```csharp
private List<Apple> Apples { get; } = new List<Apple>();
private List<Banana> Bananas { get; } = new List<Banana>();
private Grapes? Grapes { get; set; }
// ...
public void WithApples(params Apple[] apples) => Apples.AddRange(apples);
public void WithBananas(params Banana[] bananas) => Bananas.AddRange(bananas);
public void WithGrapes(Grapes grapes) => Grapes = grapes;
// ...
```
---
### Building the basket
- assemble all collected parts into the final object
- constraints of the final object can be handled within the build method
```csharp
new class FruitBasketBuilder
{
public FruitBasket Create()
{
var fruits = Apples.Cast<Fruit>().Concat(Bananas).ToList();
if(Grapes is not null)
fruits.Add(Grapes);
return new FruitBasket(fruits);
}
private List<Apple> Apples { get; } = new List<Apple>();
private List<Banana> Bananas { get; } = new List<Banana>();
private Grapes? Grapes { get; set; }
}
```
---
### Fluently chain
To allow fluently chaining the steps, just return the builder itself:
```csharp
// ...
public FruitBasketBuilder WithApples(params Apple[] apples) {
Apples.AddRange(apples);
return this;
}
// ...
```
---
{"metaMigratedAt":"2023-06-17T03:25:25.152Z","metaMigratedFrom":"YAML","title":"Technical Review Team Revit","breaks":true,"description":"an introduction into the fluent builder","contributors":"[{\"id\":\"d1e9ea52-bb3e-4e50-a92e-731218618a3b\",\"add\":8595,\"del\":7305}]"}