Design Pattern 101 — Builder Pattern

Phayao Boonon
2 min readAug 15, 2019

--

หลังจากที่ได้ทบทวน Factory Pattern ของ GoF ไปแล้ว ต่อไปจะมาดู pattern ในกลุ่มของ Creation Pattern อีกอันหนึ่งนั้นก็คือ Builder Pattern ซึ่งเป็น design pattern ที่หลายคนคุ้นเคยดี และใช้อยู่เสมอๆ ซึ่งในบทความนี้จะมาทบทวนและทำความเข้าใจว่า Builder pattern ใช้สำหรับแก้ปัญหาอะไร

Builder Pattern

Problem

ถ้าเราเป็นผู้รับเหมาก่อสร้างที่ต้องสร้างบ้านหลายๆ แบบ โดยบ้านแค่ล่ะแบบมีรูปแบบที่แตกต่างกันที่ จำนวนหน้าต่าง จำนวนประตู จำนวนห้อง มีโรงจอดรถไหม มีสวนไหม หรือมีรูปปั้นหน้าบ้านไหม เป็นต้น ซึ่งเราต้องสร้าง House class ที่มี constructor ที่รองรับ parameter ที่จำเป็นสำหรับการสร้างบ้านทั้งหมด

public class House {
private Integer windows;
private Integer doors;
private Integer rooms;
private boolean garage;
private boolean garden;
private boolean pool;
private boolean statues;

public House(Integer windows, Integer doors, Integer rooms, boolean garage, boolean garden, boolean pool, boolean statues) {
this.windows = windows;
this.doors = doors;
this.rooms = rooms;
this.garage = garage;
this.garden = garden;
this.pool = pool;
this.statues = statues;
}

// getter/setter
}

ดังนั้นถ้าเราสร้าง instance ของบ้าน (House) ในแต่ละแบบก็จะต้องระบุในส่วนที่ไม่ต้องสร้างในบ้านนั้นๆ ด้วย และที่สำคัญ constructor ที่มี parameter เยอะแบบนี้จะเป็น code smell ได้

House houseWithGarage = new House(4, 2, 4, true, false, false, false);House houseWithSwimmingPool = new House(4, 2, 4, false, false, true, false);House houseWithGarden = new House(4, 2, 4, false, false, true, false);

Solution

ในรูปแบบการสร้าง object ที่มีความซับซ้อบแบบนี้ Builder Pattern จะช่วยให้เราไม่ต้องใส่ parameter เยอะๆ แบบนี้ ด้วยการสร้าง Builder class ที่ทำหน้าที่สร้าง object ให้

ซึ่งในฐานะที่เราเป็นผู้รับเหมาก่อสร้าง เราก็จะสร้าง HouseBuilder เพื่อสร้าง House object instance ตามความต้องการของลูกค้า สร้าง method เพื่อ set parameter ต่างๆ ให้กับ object ชั่วคราว (หรือ field ของ builder เองก็ได้) โดยคืนค่าเป็น builder instance ที่กำลังสร้างอยู่ และสุดท้ายใช้ build() method สร้าง object instance ใหม่ และ return object นั้นออกไปเป็น House ในแบบที่สร้างขึ้น

public class HouseBuilder {
private House temp;

public HouseBuilder() {
temp = new House();
}

public House build() {
House house = new House();
house.setWindows(temp.getWindows());
house.setDoors(temp.getDoors());
house.setRooms(temp.getRooms());
house.setGarage(temp.isGarage());
house.setGarden(temp.isGarden());
house.setPool(temp.isPool());
house.setStatues(temp.isStatues());
return house;
}

public HouseBuilder setWindows(Integer windows) {
temp.setWindows(windows);
return this;
}

public HouseBuilder setDoors(Integer doors) {
temp.setDoors(doors);
return this;
}

public HouseBuilder setRooms(Integer rooms) {
temp.setRooms(rooms);
return this;
}

public HouseBuilder setGarage(boolean garage) {
temp.setGarage(garage);
return this;
}

public HouseBuilder setGarden(boolean garden) {
temp.setGarden(garden);
return this;
}

public HouseBuilder setPool(boolean pool) {
temp.setPool(pool);
return this;
}

public HouseBuilder setStatues(boolean statues) {
temp.setStatues(statues);
return this;
}
}

แล้วเราจะใช้ HouseBuilder นี้อย่างไร โดยใช้ HouseBuilder กลับไปสร้าง object ของบ้าน 3 แบบข้างต้น ได้ดังนี้

HouseBuilder builder = new HouseBuilder();
House houseWithGarage = builder.setWindows(4)
.setDoors(2)
.setRooms(4)
.setGarage(true)
.build();

House houseWithSwimmingPool = builder.setWindows(4)
.setDoors(2)
.setRooms(4)
.setPool(true)
.build();

House houseWithGarden = builder.setWindows(4)
.setDoors(2)
.setRooms(4)
.setGarden(true)
.build();

จะเห็นได้ว่าเราทำการ set ค่าเฉพาะในส่วนที่เราต้องสร้างบ้านในแต่ละหลังที่แตกต่างจากหลังอื่น ส่วนค่าอื่นนั้นให้เป็นค่า defult ที่เป็นมีค่าเป็น FALSE อยู่แล้ว

Builder Pattern เป็นการซ่อน (Encapsulate) วิธีสร้าง object ที่มีความซับซ้อน และทำให้ object ที่สร้างขึ้นมีหลายขั้นตอน และใช้ขั้นตอนที่หลากหลายได้

สรุป

จากการทบทวนใช้ Builder Pattern ซึ่งเป็น creation pattern มาสร้าง class ที่ใช้สร้าง object instance ทำให้เราสร้าง object ไม่จำเป็นต้องใช้ constructor ที่ต้องใส่ parameter ทั้งหมด ซึ่งเป็นโอกาสทำให้เกิด code smell ได้ เมื่อใช้ Builder pattern ก็จะแก้ปัญหานี้ได้ แต่ถ้าเป็นสาย Java และใช้ Lombok ซึ่งมี @Builder annotation ทำให้ class เป็น Builder class ได้ง่ายเช่นเดียวกัน

--

--

Phayao Boonon
Phayao Boonon

Written by Phayao Boonon

Software Engineer 👨🏻‍💻 Stay Hungry Stay Foolish

No responses yet