ข้ามไปยังเนื้อหา

Design Patterns คืออะไร

Design pattern คือคำอธิบายวิธีแก้ปัญหาที่มีชื่อเรียกและนำกลับมาใช้ซ้ำได้ สำหรับปัญหาที่มักโผล่ขึ้นมาเรื่อย ๆ เมื่อคุณจัดวาง object และ class ไม่ใช่ code สำเร็จรูปที่คุณก๊อปไปวางในโปรเจกต์ แต่ใกล้เคียงกับสูตรอาหารหรือพิมพ์เขียวมากกว่า pattern บอกคุณว่าต้องสร้างส่วนไหนบ้าง ส่วนเหล่านั้นควรสัมพันธ์กันอย่างไร และการจัดวางนี้สร้างสมดุลให้กับแรงผลักดันอะไรบ้าง — จากนั้นคุณก็นำรูปทรงนั้นไปปรับให้เข้ากับ type และข้อจำกัดที่เป็นรูปธรรมของคุณเอง

มีสองแนวคิดที่สำคัญตรงนี้ อย่างแรก pattern เกี่ยวกับปัญหาที่เกิดขึ้นซ้ำ ๆ ถ้าความยุ่งยากโผล่ขึ้นมาแค่ครั้งเดียว คุณก็แค่แก้ปัญหานั้นไป pattern จะได้ชื่อของตัวเองก็ต่อเมื่อปัญหารูปทรงเดียวกันปรากฏขึ้นครั้งแล้วครั้งเล่าในระบบที่ไม่เกี่ยวข้องกัน อย่างที่สอง pattern มอบคำศัพท์ให้คุณ การพูดว่า “เอา Facade ไปวางหน้า subsystem นั้นกัน” สื่อสารการออกแบบทั้งชุด — ทั้งโครงสร้าง เจตนา และข้อแลกเปลี่ยน — ภายในสองคำ เหมือนที่นักหมากรุกพูดว่า “fork” แทนที่จะอธิบายทั้งกระดาน

เป็นเรื่องง่ายที่จะเข้าใจผิดว่าสิ่งที่มีประโยชน์อื่น ๆ เป็น pattern มีสามข้อแยกแยะที่ช่วยรักษาความหมายของคำนี้ให้ถูกต้อง:

  • ไม่ใช่ code ก๊อปแปะ pattern คือไอเดียด้านการออกแบบที่แสดงออกในระดับของบทบาทและความสัมพันธ์ pattern เดียวกันมีหน้าตาต่างกันใน TypeScript, Python, Go และ Rust เพราะแต่ละภาษามีวิธีแสดงโครงสร้างเดียวกันในแบบของตัวเอง
  • ไม่ใช่ idiom idiom คือธรรมเนียมระดับล่างที่เฉพาะเจาะจงกับภาษา — list comprehension ใน Python หรือรูปแบบ comma-ok ใน Go idiom มีคุณค่า แต่อยู่ในระดับที่ต่ำกว่า design pattern
  • ไม่ใช่ anti-pattern anti-pattern คือวิธีแก้ปัญหาทั่วไปที่ดูสมเหตุสมผลแต่กลับให้ผลย้อนแย้งอย่างสม่ำเสมอ — God Object ที่ทำทุกอย่าง หรือ Singleton ที่แอบเอามาใช้เป็น global state pattern อธิบายสิ่งที่มักได้ผล ส่วน anti-pattern ตั้งชื่อให้สิ่งที่มักสร้างความเจ็บปวด

แคตตาล็อกคลาสสิกจัดกลุ่ม pattern ออกเป็นสามตระกูลตามชนิดของปัญหาที่จัดการ: object ถูกสร้างขึ้นอย่างไร object ถูกประกอบเป็นโครงสร้างที่ใหญ่ขึ้นอย่างไร และ object โต้ตอบกันอย่างไรตอน runtime

flowchart TD
  P[Design Patterns]
  P --> C[Creational]
  P --> S[Structural]
  P --> B[Behavioral]
  C --> C1[how objects get created]
  S --> S1[how objects are composed]
  B --> B1[how objects communicate]
สามตระกูลของ pattern และคำถามที่แต่ละตระกูลตอบ
  • Creational pattern ควบคุมว่า object เกิดขึ้นมาอย่างไร — เลือก concrete type แชร์ instance เดียวกัน หรือประกอบสิ่งที่ซับซ้อนทีละขั้น
  • Structural pattern อธิบายว่า object และ class รวมกันเป็นโครงสร้างที่ใหญ่ขึ้นอย่างไร โดยยังคงความยืดหยุ่นและประสิทธิภาพของโครงสร้างเหล่านั้นไว้
  • Behavioral pattern เกี่ยวข้องกับว่าความรับผิดชอบและข้อความไหลเวียนระหว่าง object อย่างไรตอน runtime

ทุกบทเรียนเป็นไปตามรูปแบบเดียวกัน เพื่อให้คุณรู้เสมอว่าต้องมองหาอะไรตรงไหน: intent ในประโยคเดียว problem ที่แก้ ไดอะแกรม UML structure หนึ่ง example ที่ทำให้ดูใน TypeScript, Python, Go และ Rust ตามด้วย trade-offs และแบบทดสอบสั้น ๆ ก่อนจะดำดิ่งลงไปในแคตตาล็อก โมดูลนี้จะปูพื้นให้คุณกับหลักการพื้นฐาน — SOLID, composition over inheritance และโน้ตเทชัน UML ที่ใช้ตลอดทั้งคอร์ส — เพื่อให้แต่ละ pattern อ่านแล้วเหมือนเป็นการนำไอเดียที่คุณเข้าใจอยู่แล้วมานำไปใช้ มากกว่าจะเป็นเทคนิคที่ต้องท่องจำ

ข้อใดอธิบาย design pattern ได้ดีที่สุด?
อะไรที่ทำให้ idiom ต่างจาก design pattern?
behavioral pattern จัดการกับคำถามใดเป็นหลัก?