Builder Pattern
[tr] Türkçe Oku 2023-06-11
Once upon a time, there was a very beautiful kingdom, and its name was “Builder Pattern”. Everything in this kingdom was about the art of constructing complex objects step by step and connecting them together. These complex objects were the most valuable treasures of the kingdom, and each one was carefully and thoughtfully constructed.
The wisest person in the kingdom was this master named the Builder. The Builder would construct complex objects using materials like stones, bricks, and wood. But the Builder didn’t do everything on his own. He had a Director to assist him. The Director would tell the Builder which parts to construct in what order. This way, the Director made sure that the Builder could focus solely on the construction of the object.
This story is implemented in the C# language as follows:
public interface IBuilder
{
void BuildPartA();
void BuildPartB();
void BuildPartC();
}
public class ConcreteBuilder : IBuilder
{
public void BuildPartA()
{
// Build PartA
}
public void BuildPartB()
{
// Build PartB
}
public void BuildPartC()
{
// Build PartC
}
}
public class Director
{
public void Construct(IBuilder builder)
{
builder.BuildPartA();
builder.BuildPartB();
builder.BuildPartC();
}
}
The same story in Java:
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
}
public class ConcreteBuilder implements Builder {
public void buildPartA() {
// Build PartA
}
public void buildPartB() {
// Build PartB
}
public void buildPartC() {
// Build PartC
}
}
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
In Python:
from abc import ABC, abstractmethod
class Builder(ABC):
@abstractmethod
def build_part_a(self):
pass
@abstractmethod
def build_part_b(self):
pass
@abstractmethod
def build_part_c(self):
pass
class ConcreteBuilder(Builder):
def build_part_a(self):
# Build PartA
pass
def build_part_b(self):
# Build PartB
pass
def build_part_c(self):
# Build PartC
pass
class Director:
def construct(self, builder):
builder.build_part_a()
builder.build_part_b()
builder.build_part_c()
In Go:
type Builder interface {
BuildPartA()
BuildPartB()
BuildPartC()
}
type ConcreteBuilder struct{}
func (b *ConcreteBuilder) BuildPartA() {
// Build PartA
}
func (b *ConcreteBuilder) BuildPartB() {
// Build PartB
}
func (b *ConcreteBuilder) BuildPartC() {
// Build PartC
}
type Director struct{}
func (d *Director) Construct(builder Builder) {
builder.BuildPartA()
builder.BuildPartB()
builder.BuildPartC()
}
And in Rust:
pub trait Builder {
fn build_part_a(&mut self);
fn build_part_b(&mut self);
fn build_part_c(&mut self);
}
pub struct ConcreteBuilder;
impl Builder for ConcreteBuilder {
fn build_part_a(&mut self) {
// Build PartA
}
fn build_part_b(&mut self) {
// Build PartB
}
fn build_part_c(&
mut self) {
// Build PartC
}
}
pub struct Director;
impl Director {
pub fn construct(&self, builder: &mut dyn Builder) {
builder.build_part_a();
builder.build_part_b();
builder.build_part_c();
}
}
And thus, we saw how the Builder and the Director constructed these complex objects. Building each part separately and in order was critical for the final form of the object. Also, the presence of the Director helps determine how and in what order the Builder should work. This makes the code more orderly, understandable, and flexible because we can create different objects using different Builders. This story demonstrates how the Builder design pattern works and how it can be used. This pattern provides a way to construct complex objects and facilitates the maintenance and extendability of the code.