1. การใช้งาน Design Pattern ของ Decorator

Decorator pattern คือ design pattern ทางโครงสร้างที่อนุญาตให้เพิ่มคุณลักษณะเสริมให้กับออบเจ็กต์ได้โดยไม่ต้องแก้ไขโค้ดของออบเจ็กต์ มันทำได้โดยการห่อหุ้มออบเจ็กต์ด้วยคลาส decorator เพื่อให้สามารถเพิ่ม ปรับเปลี่ยน หรือเสริมความสามารถของออบเจ็กต์ในเวลารันไทม์

2. ลักษณะและข้อดีของ Pattern ของ Decorator

ลักษณะและข้อดีของ pattern ของ Decorator ประกอบด้วย:

  • การขยายความสามารถของออบเจ็กต์ได้ที่ไม่ต้องแก้ไขโค้ด
  • ปฏิบัติตนตามหลัก Open-Closed โดยอนุญาตให้เพิ่มหรือลบ decorator ได้ในเวลารันไทม์
  • สามารถรวม decorator หลายๆ อันเข้าด้วยกันเพื่อสร้างความสามารถที่ต่างกันได้
  • โปร่งใสว่า decorator ไม่เกี่ยวข้องกับวิธีการที่ออบเจ็กต์ถูกตกแต่งได้ ทำให้สามารถเปลี่ยนแปลงได้อิสรณ์

3. ตัวอย่างของการประยุกต์ใช้งานปฏิบัติการ Pattern ของ Decorator

Pattern ของ Decorator มีการประยุกต์ใช้งานอย่างแพร่หลายในการพัฒนาซอฟต์แวร์ เช่น:

  • เพิ่มความสามารถในการล็อกข้อมูลไดนามิก
  • เพิ่มความสามารถในการกำกับข้อมูล
  • การตรวจสอบข้อมูลไดนามิก

4. การประยุกต์ใช้งาน Pattern ของ Decorator ใน Golang

4.1. UML แผนภาพคลาส

Decorator Pattern ใน Golang

4.2. ประเภทตัวอย่าง

ในตัวอย่าง เรามีอินเตอร์เฟซของ Component และคลาส ConcreteComponent ที่โดยสารว่า Operation ของอินเตอร์เฟซ Component

จากนั้นเรามีคลาสของ Decorator ที่ยังทำการโอเวอร์ไรด์อินเตอร์เฟซของ Component คลาส Decorator มีตัวแปรชนิดของ Component

ทั้ง ConcreteDecoratorA และ ConcreteDecoratorB คลาสสืบทอดจาก Decorator และโอเวอร์ไรด์ความสามารถเพิ่มเติมด้วยการโอเวอร์ไรด์อินเตอร์เฟซ Operation

4.3. ขั้นตอนการประยุกต์ใช้งาน 1: กำหนดอินเตอร์เฟซและคลาสอิมพลีเมนต์

type Component interface {
	Operation() string
}

type ConcreteComponent struct {}

func (c *ConcreteComponent) Operation() string {
	return "specific component operation"
}

4.4. ขั้นตอนการประยุกต์ใช้งาน 2: กำหนด decorator

type Decorator struct {
	component Component
}

func (d *Decorator) Operation() string {
	return d.component.Operation()
}

4.5. ขั้นตอนการประยุกต์ใช้งาน 3: การใช้งาน decorator

type ConcreteDecoratorA struct {
	Decorator
	addedState string
}

func (c *ConcreteDecoratorA) Operation() string {
	c.addedState = "New State"
	return c.addedState + " " + c.component.Operation()
}

type ConcreteDecoratorB struct {
	Decorator
}

func (c *ConcreteDecoratorB) Operation() string {
	return "specific decorator B operation " + c.component.Operation()
}

4.6. ขั้นตอนการประยุกต์ใช้งาน 4: การใช้ decorator

func main() {
	component := &ConcreteComponent{}

	decoratorA := &ConcreteDecoratorA{}
	decoratorA.component = component

	decoratorB := &ConcreteDecoratorB{}
	decoratorB.component = decoratorA

	result := decoratorB.Operation()
	fmt.Println(result)
}

5. การเปรียบเทียบ Pattern ของ Decorator กับ Pattern อื่นๆ

5.1. การเปรียบเทียบกับการสืบทอด (Inheritance)

เมื่อเปรียบเทียบกับการสืบทอด เพจจะสังเกตได้ว่า pattern ของ decorator สามารถเพิ่มความสามารถได้โดยไม่ต้องแก้ไขโค้ดที่มีอยู่ ในขณะที่การสืบทอดเป็นสถานะและต้องกำหนดตั้งแต่เวลาคอมไพล์

5.2. การเปรียบเทียบกับ Pattern ของ Static Proxy

Pattern ของ Decorator และ pattern ของ Static Proxy สามารถทำการขยายฟังก์ชันได้ทั้งคู่ แต่ pattern ของ Decorator มีความยืดหยุ่นมากกว่าและอนุญาตให้เพิ่มหรือลบความสามารถได้ในเวลารันไทม์

5.3. การเปรียบเทียบกับ pattern ของ Dynamic Proxy

ทั้ง pattern ของ decorator และ pattern ของ Dynamic Proxy สามารถขยายความสามารถของออบเจ็กต์ได้ในเวลารันไทม์ แต่ pattern ของ decorator จะตกแต่งออบเจ็กต์เดียว ในขณะที่ pattern ของ Dynamic Proxy มีความเกี่ยวพันกับการเข้าถึงทางอ้อมะรละหลังระหว่างออบเจ็กต์โปรกซี่และออบเจ็กต์เป้าหมาย