1. Apa itu Pola Flyweight
1.1 Definisi dan Konsep
Pola Flyweight adalah pola desain struktural yang tujuan utamanya adalah meminimalkan jumlah objek yang dibagikan, sehingga menghemat memori dan meningkatkan kinerja. Pola Flyweight mengurangi pembuatan dan penggunaan objek dengan cara membagikan objek yang sama atau serupa, mencapai optimasi kinerja.
1.2 Perbedaan dengan Pola Desain Lainnya
Dibandingkan dengan pola desain lain, Pola Flyweight lebih fokus pada pembagian dan penggunaan kembali objek. Pola ini memisahkan objek menjadi status internal yang dapat dibagikan dan status eksternal yang tidak dapat dibagikan. Dengan berbagi status internal, pola ini mengurangi pembuatan dan konsumsi memori objek, meningkatkan efisiensi sistem.
2. Karakteristik dan Keunggulan Pola Flyweight
Karakteristik dan keunggulan utama dari Pola Flyweight meliputi:
- Penggunaan memori yang diminimalkan: Ini mengurangi konsumsi memori dengan membagikan objek yang sama atau serupa.
- Kinerja yang ditingkatkan: Ini mengurangi pembuatan dan penghapusan objek, mempercepat operasi sistem.
- Mendukung jumlah objek yang sangat halus: Pola ini dapat membuat sejumlah besar objek yang sangat halus tanpa banyak memakan ruang memori.
- Struktur sistem yang disederhanakan: Dengan memisahkan status internal dan eksternal objek, pola ini menyederhanakan struktur dan kompleksitas sistem.
3. Contoh Penerapan Praktis Pola Flyweight
Pola Flyweight dapat diterapkan dalam skenario berikut:
- Objek partikel dalam game: Properti dari setiap objek partikel dapat dibagi menjadi status internal dan eksternal, dan objek partikel dengan properti yang sama dapat dibagikan.
- Objek koneksi dalam server jaringan: Properti objek koneksi dapat dibagi menjadi status internal dan eksternal, dan objek koneksi yang ada dapat digunakan kembali sebelum didaur ulang.
4. Implementasi Pola Flyweight dalam Golang
4.1 Diagram Kelas UML
Diagram kelas UML dari Pola Flyweight dalam Golang adalah sebagai berikut:
4.2 Pengantar Contoh
Dalam contoh ini, kita akan membuat editor grafis berdasarkan Pola Flyweight, yang berisi lingkaran dengan berbagai warna, dan mengurangi penggunaan memori dengan membagikan objek lingkaran dengan warna yang sama.
4.3 Langkah Implementasi
4.3.1 Membuat Interface Flyweight dan Kelas Concrete Flyweight
Pertama, kita perlu membuat interface Flyweight
untuk mendefinisikan operasi objek yang dibagikan. Kemudian, kita dapat membuat kelas ConcreteFlyweight
untuk mengimplementasikan interface Flyweight
dan meliputi status internal.
// Flyweight mendefinisikan interface objek flyweight
type Flyweight interface {
Operation(extrinsicState string)
}
// ConcreteFlyweight mewakili objek flyweight konkret, mengimplementasikan interface Flyweight
type ConcreteFlyweight struct {
intrinsicState string
}
// Operation mengimplementasikan metode operasi dari objek yang dibagikan
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
fmt.Printf("Objek flyweight konkret, status internal: %s, status eksternal: %s\n", f.intrinsicState, extrinsicState)
}
4.3.2 Membuat Kelas FlyweightFactory
Selanjutnya, kita dapat membuat kelas FlyweightFactory
untuk mengelola dan membagikan objek flyweight. Kelas pabrik ini memelihara kamus flyweights
untuk menyimpan objek flyweight yang telah dibuat.
// Kelas FlyweightFactory
type FlyweightFactory struct {
flyweights map[string]Flyweight
}
// GetFlyweight mengambil atau membuat objek flyweight dari pabrik
func (f *FlyweightFactory) GetFlyweight(key string) Flyweight {
if fw, ok := f.flyweights[key]; ok {
return fw
}
flyweight := &ConcreteFlyweight{
intrinsicState: key,
}
f.flyweights[key] = flyweight
return flyweight
}
4.3.3 Contoh Pemanggilan Klien
Terakhir, kita dapat membuat kelas Client
untuk menunjukkan bagaimana menggunakan pola flyweight untuk mengimplementasikan editor grafis.
// Kelas Klien
type Client struct {
flyweight Flyweight
}
// Operation melakukan suatu operasi
func (c *Client) Operation() {
c.flyweight.Operation("status eksternal")
}
4.4 Pertimbangan Implementasi dan Praktik Terbaik
4.4.1 Berbagi State dan Keamanan Thread
Saat menggunakan pola flyweight, perhatian perlu diberikan pada berbagi state internal dan keamanan thread. Karena objek flyweight dibagikan oleh beberapa klien, penting untuk memastikan konsistensi dari state internal.
4.4.2 Manajemen Penyimpanan Objek Pool
Untuk lebih baik mengelola dan menggunakan kembali objek flyweight, pool objek dapat digunakan untuk menyimpan objek flyweight yang telah dibuat. Pool objek dapat meningkatkan tingkat penggunaan kembali objek dan mengurangi overhead dari pembuatan dan penghapusan objek.
4.4.3 Manajemen Eksternal dari State Objek
Pola flyweight memisahkan state internal dan eksternal objek, tetapi state eksternal perlu dikelola oleh klien. Saat menggunakan objek flyweight, klien perlu meneruskan state eksternal ke objek flyweight untuk melakukan operasi.
Contoh Kode Lengkap
Di bawah ini adalah contoh kode lengkap dalam Golang:
package main
import "fmt"
// Flyweight mendefinisikan antarmuka dari objek flyweight
type Flyweight interface {
Operation(extrinsicState string)
}
// ConcreteFlyweight mewakili objek flyweight spesifik dan mengimplementasikan antarmuka Flyweight
type ConcreteFlyweight struct {
intrinsicState string
}
// Operation mengimplementasikan metode operasi untuk objek yang dibagikan
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
fmt.Printf("Objek flyweight konkret, state internal: %s, state eksternal: %s\n", f.intrinsicState, extrinsicState)
}
// Kelas FlyweightFactory
type FlyweightFactory struct {
flyweights map[string]Flyweight
}
// GetFlyweight mengambil atau membuat objek flyweight dari pabrik
func (f *FlyweightFactory) GetFlyweight(key string) Flyweight {
if fw, ok := f.flyweights[key]; ok {
return fw
}
flyweight := &ConcreteFlyweight{
intrinsicState: key,
}
f.flyweights[key] = flyweight
return flyweight
}
// Kelas Klien
type Client struct {
flyweight Flyweight
}
// Operation melakukan sebuah operasi
func (c *Client) Operation() {
c.flyweight.Operation("state eksternal")
}
func main() {
factory := &FlyweightFactory{
flyweights: make(map[string]Flyweight),
}
flyweight1 := factory.GetFlyweight("A")
flyweight1.Operation("state eksternal 1")
flyweight2 := factory.GetFlyweight("B")
flyweight2.Operation("state eksternal 2")
client := &Client{
flyweight: factory.GetFlyweight("A"),
}
client.Operation()
}