/ OOD

[365 วันแห่งโปรแกรม #day51] Builder pattern

วันที่ห้าสิบเอ็ดของ ‪#‎365วันแห่งโปรแกรม เหมือนจะไม่จริงเท่าไหร่ที่ผมเคยบอกว่าเรื่อง Design Pattern นั้นเป็นสิ่งที่ชัดเจน มันไม่ใช่ไม่ชันเจนหรอก แต่บางทีมันก็ยากเกินไป = =" วันนี้เรายังอยู่กับ pattern ประเภท creational ครับ และเรื่องนั้นก็คือ Builder pattern


Builder pattern

Builder pattern เกิดขึ้นมาเพื่อแก้ปัญหาการสร้าง object ที่ซับซ้อน เช่น มีพารามิเตอร์จำนวนมาก ต้อง initial หลายอย่าง หรืออื่นๆ ฟังดูก็แทบไม่ต่างอะไรจาก Factory เลย แต่จริงๆ แล้วต่างครับ ต่างตรงที่จุดประสงค์ของ Builder คือการสร้าง object ที่ complex ต้องทำงานหลาย step แต่ Factory เน้นการสร้าง object แบบรวดเร็ว call method ครั้งเดียวเสร็จเลย

ตามอุดมคติแล้ว Builder pattern จะประกอบด้วย 2 ส่วนคือ Director และ Builder components โดย Director จะเป็นตัวที่ encapsulate การทำงานเอาไว้ ส่วน Builder เป็นผู้สร้าง object การทำงานจะเริ่มจาก Client บอก Director ให้สร้าง object ให้ ผ่านทาง Builder อย่างไรก็ตามในหลายครั้งพบว่า Director นั้นทำให้ความยืดหยุ่นในการใช้งานน้อยลง ดังนั้นจึงพบการใช้งาน Builder แบบไม่ผ่าน Director บ่อยครั้ง เช่นใน StringBuilder ของจาวา หรือ UriBuilder ของ C#

Builder pattern

การใช้งาน Builder pattern

ตัวอย่างที่ง่ายที่สุดน่าจะเป็นเรื่องของการสั่งอาหารชุด Happy Meal ครับ ทุกคนน่าจะเคยสั่งกันอยู่แล้วนะครับ ในชุดก็จะมีไก่ทอดหรือเบอเกอร์ เครื่องดื่ม เฟรนช์ฟรายด์ และที่สำคัญคือของเล่น จะเห็นว่าถ้าเราต้องการสร้าง object ของชุด Happy Meal นี้ก็ต้องใช้หลายขั้นตอนมาก ถ้าเรามาลองใช้ Builder pattern ก็จะได้ตาม Sequence diagram ด้านล่างนี้ครับ

Happy Meal

จะเห็นว่า Customer ก็แค่สั่ง Cashier ว่าของชุด Happy Meal ครับ เสร็จแล้วพนักงานก็จะไปจัดอาหารมาให้ ถ้าเขียนเป็นโค้ดก็จะได้ประมาณนี้ครับ

interface Meal {}

class HappyMeal implements Meal{}

interface MealBuilder{
    public void addItem();
    public Meal getMeal();
}

class HappyMealBuilder implements MealBuilder{
    public void addItem(){...}
    public Meal getMeal(){...}
}

class Cashire{
    public Meal makeMeal(MealBuilder builder){
        builder.addItem();
        ...
        return builder.getMeal();
    }
}

จะเห็นว่า Cashier เป็นคนระบุทุกอย่างเลยว่าจะใส่อะไรในชุดบ้าง ซึ่งก็เป็นการ encapsulate กระบวนการทำงานครับ เพราะลูกค้าไม่ควรต้องรู้ว่าต้องใส่อะไรบ้าง อย่างไรก็ตาม Cashier นั้นกลับเป็นตัวปัญหาที่ทำให้การ customize เมนูยากขึ้น เช่นถ้าอยากเลือกของเล่นล่ะ ถ้าอยากเลือกไก่ทอดล่ะ วิธีแก้ก็คือก็เพิ่ม parameter ให้ method ของ Cashier ครับ หรือไม่ก็เรียกใช้ Builder ตรงโดยไม่ผ่าน Cashier เลย ทั้งสองแบบก็มีข้อดีข้อเสียต่างกันครับ

ตัวอย่างของกรณีที่ไม่ใช้ Director

UriBuilder u2 = new UriBuilder();
u2.Host = "www.dotnetperls.com";
u2.Path = "uribuilder";
u2.Scheme = "http"; 

====output====
http://www.dotnetperls.com/uribuilder

References

Builder pattern

What is the difference between Builder Design pattern and Factory Design pattern?

Builder Pattern

The builder pattern in practice

Builder Design Pattern

Too Many Parameters in Java Methods, Part 3: Builder Pattern

When would you use the Builder Pattern?

analytically/innerbuilder

Design Patterns - Builder Pattern

Builder Pattern : Why does the Director construct the object?

Builder design pattern: why do we need a Director?

Design Patterns Uncovered: The Builder Pattern

C# UriBuilder Class

#‎day51 #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...