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:

Pola Flyweight dalam Golang

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()
}