1. Apa itu Pola Dekorator

Pola dekorator adalah pola desain struktural yang memungkinkan penambahan fitur tambahan ke dalam objek secara dinamis tanpa memodifikasi kode objek tersebut. Hal ini dicapai dengan melingkupi objek dalam sebuah kelas dekorator, memberikan kemampuan untuk menambah, memodifikasi, atau meningkatkan perilaku objek saat runtime.

2. Karakteristik dan Kelebihan Pola Dekorator

Karakteristik dan kelebihan dari pola dekorator meliputi:

  • Memperluas fungsionalitas suatu objek secara dinamis tanpa memodifikasi kode tersebut.
  • Patuh terhadap Prinsip Terbuka-Tertutup, memungkinkan penambahan dan penghapusan dekorator secara dinamis.
  • Kemampuan untuk menggabungkan beberapa dekorator untuk mencapai perluasan fungsionalitas bertingkat.
  • Dekorator independen dari cara objek dihias, memungkinkan perubahan dilakukan secara independen.

3. Contoh Aplikasi Praktis dari Pola Dekorator

Pola dekorator memiliki banyak aplikasi praktis dalam pengembangan perangkat lunak, seperti:

  • Menambahkan fungsionalitas logging secara dinamis
  • Menambahkan fungsionalitas caching secara dinamis
  • Validasi data dinamis

4. Implementasi Pola Dekorator di Golang

4.1. Diagram Kelas UML

Pola Dekorator di Golang

4.2. Pengantar Contoh

Dalam contoh ini, kita memiliki sebuah antarmuka Komponen dan sebuah kelas ConcreteComponent yang mengimplementasikan metode Operasi dari antarmuka Komponen.

Kemudian kita memiliki sebuah kelas Dekorator yang juga mengimplementasikan antarmuka Komponen. Kelas Dekorator memiliki variabel anggota bertipe Komponen.

Kedua kelas ConcreteDecoratorA dan ConcreteDecoratorB mewarisi dari kelas Dekorator dan mengimplementasikan fungsionalitas tambahan dengan mengganti metode Operasi.

4.3. Langkah Implementasi 1: Mendefinisikan antarmuka dan kelas implementasi

type Component interface {
	Operation() string
}

type ConcreteComponent struct {}

func (c *ConcreteComponent) Operation() string {
	return "operasi komponen spesifik"
}

4.4. Langkah Implementasi 2: Mendefinisikan dekorator

type Decorator struct {
	component Component
}

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

4.5. Langkah Implementasi 3: Implementasi dekorator

type ConcreteDecoratorA struct {
	Decorator
	addedState string
}

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

type ConcreteDecoratorB struct {
	Decorator
}

func (c *ConcreteDecoratorB) Operation() string {
	return "operasi dekorator B spesifik " + c.component.Operation()
}

4.6. Langkah Implementasi 4: Menggunakan dekorator

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

	dekoratorA := &ConcreteDecoratorA{}
	dekoratorA.component = komponen

	dekoratorB := &ConcreteDecoratorB{}
	dekoratorB.component = dekoratorA

	hasil := dekoratorB.Operation()
	fmt.Println(hasil)
}

5. Perbandingan Pola Dekorator dengan Pola Desain Lain

5.1. Perbandingan dengan Pewarisan

Dibandingkan dengan pewarisan, pola dekorator dapat dinamis menambahkan fungsionalitas tanpa memodifikasi kode yang ada, sedangkan pewarisan adalah statis dan perlu ditentukan saat waktu kompilasi.

5.2. Perbandingan dengan Pola Proxy Statis

Pola dekorator dan pola proxy statis dapat sama-sama mencapai perluasan fungsi, namun pola dekorator lebih fleksibel dan memungkinkan penambahan dan penghapusan fungsionalitas secara dinamis.

5.3. Perbandingan dengan Pola Proxy Dinamis

Baik pola dekorator maupun pola proxy dinamis dapat memperluas fungsionalitas objek saat runtime. Namun, pola dekorator menghias sebuah objek tunggal, sementara pola proxy dinamis melibatkan akses tidak langsung antara objek proxy dan objek target.