Flyweight Pattern #

Flyweight Pattern adalah salah satu structural design pattern yang berfokus pada efisiensi penggunaan memori. Pattern ini sangat berguna ketika aplikasi harus menangani banyak sekali objek kecil yang memiliki data yang sama atau mirip, sehingga pembuatan objek secara terpisah akan memakan memori berlebihan.

Dengan Flyweight, kita memisahkan state yang bisa dibagi (intrinsic state) dan state yang tidak bisa dibagi (extrinsic state), lalu menggunakan kembali (reuse) objek yang sama untuk konteks yang berbeda.

Apa itu Flyweight Pattern? #

Flyweight Pattern adalah pola desain yang bertujuan untuk mengurangi konsumsi memori dengan cara berbagi objek (shared objects) alih-alih membuat objek baru setiap kali dibutuhkan.

Inti dari Flyweight Pattern:

  • Objek dibagi menjadi dua jenis state:

    • Intrinsic state → data yang immutable dan bisa dibagikan
    • Extrinsic state → data yang context-dependent dan disuplai dari luar
  • Objek flyweight disimpan dalam sebuah factory atau pool

  • Klien tidak langsung membuat objek, tetapi meminta ke factory


Tujuan dari Pattern #

Flyweight Pattern digunakan untuk:

  1. Menghemat memori pada aplikasi berskala besar
  2. Mengurangi jumlah object instantiation
  3. Meningkatkan performa dengan reuse objek
  4. Menjaga konsistensi data intrinsic

Pattern ini sangat efektif ketika:

  • Banyak objek memiliki konfigurasi atau data dasar yang sama
  • Objek bersifat ringan tetapi jumlahnya sangat besar

Kapan Cocok Digunakan? #

Gunakan Flyweight Pattern ketika:

  • Aplikasi membuat ribuan hingga jutaan objek kecil
  • Banyak objek memiliki state yang identik
  • Biaya pembuatan objek cukup mahal
  • Identitas objek tidak terlalu penting (object identity tidak krusial)

Contoh kasus nyata #

  • Rendering karakter pada text editor
  • Game (peluru, partikel, pohon, rumput)
  • Sistem cache konfigurasi
  • Icon / image sharing
  • Font rendering

Struktur Pattern #

Komponen utama:

  1. Flyweight (interface / struct)

    • Mendefinisikan operasi dengan extrinsic state
  2. ConcreteFlyweight

    • Implementasi flyweight dan menyimpan intrinsic state
  3. FlyweightFactory

    • Mengelola dan menyediakan flyweight yang sudah ada
  4. Client

    • Menyediakan extrinsic state

Contoh Implementasi (Golang) #

Studi Kasus #

Misalkan kita membuat sistem text editor yang menampilkan banyak karakter.

  • Intrinsic state: jenis karakter (char), font
  • Extrinsic state: posisi (x, y)

Flyweight (Character) #

package flyweight

type Character struct {
	char string
	font string
}

func (c *Character) Render(x, y int) {
	// extrinsic state: posisi
	fmt.Printf("Render '%s' with font %s at (%d,%d)\n", c.char, c.font, x, y)
}

Flyweight Factory #

package flyweight

import "fmt"

type CharacterFactory struct {
	characters map[string]*Character
}

func NewCharacterFactory() *CharacterFactory {
	return &CharacterFactory{
		characters: make(map[string]*Character),
	}
}

func (f *CharacterFactory) GetCharacter(char, font string) *Character {
	key := char + font

	if c, ok := f.characters[key]; ok {
		return c
	}

	fmt.Println("Create new flyweight for:", char, font)
	c := &Character{char: char, font: font}
	f.characters[key] = c
	return c
}

Client Code #

package main

import "flyweight"

func main() {
	factory := flyweight.NewCharacterFactory()

	chars := []struct {
		char string
		x    int
		y    int
	}{
		{"A", 0, 0},
		{"A", 10, 0},
		{"B", 20, 0},
		{"A", 30, 0},
	}

	for _, c := range chars {
		ch := factory.GetCharacter(c.char, "Arial")
		ch.Render(c.x, c.y)
	}
}

Output (Ilustrasi) #

Create new flyweight for: A Arial
Render 'A' with font Arial at (0,0)
Render 'A' with font Arial at (10,0)
Create new flyweight for: B Arial
Render 'B' with font Arial at (20,0)
Render 'A' with font Arial at (30,0)

Terlihat bahwa karakter A dengan font Arial hanya dibuat satu kali dan digunakan kembali.


Kelebihan dan Kekurangan #

Kelebihan #

  • Penghematan memori signifikan
  • Performa meningkat pada skala besar
  • Konsistensi data intrinsic

Kekurangan #

  • Kompleksitas kode bertambah
  • Debugging lebih sulit
  • Tidak cocok untuk semua kasus

Flyweight vs Object Pool #

AspekFlyweightObject Pool
FokusMemory sharingResource reuse
StateImmutableMutable
LifecyclePanjangPendek

Best Practices #

1. Pastikan Objek Bersifat Immutable #

Intrinsic state tidak boleh berubah, agar aman dibagi ke banyak context.

2. Gunakan Factory sebagai Single Source #

Jangan biarkan client membuat flyweight secara langsung.

3. Hati-hati dengan Over-Engineering #

Jika jumlah objek sedikit, Flyweight justru menambah kompleksitas.

4. Perhatikan Concurrency #

Di Golang:

  • Gunakan sync.Mutex atau sync.Map jika factory diakses banyak goroutine
var mu sync.Mutex

mu.Lock()
defer mu.Unlock()

5. Pisahkan dengan Jelas Intrinsic vs Extrinsic State #

Jika boundary ini kabur, Flyweight akan sulit dipelihara.


Penutup #

Flyweight Pattern adalah solusi elegan untuk masalah memory explosion akibat banyaknya objek serupa. Dengan memisahkan intrinsic dan extrinsic state serta menerapkan reuse melalui factory, aplikasi bisa menjadi jauh lebih efisien.

Namun, seperti pattern lainnya, Flyweight tidak selalu diperlukan. Gunakan ketika benar-benar ada kebutuhan skala dan tekanan memori.

Jika digunakan dengan tepat, Flyweight bisa menjadi game changer pada sistem berskala besar seperti editor, game engine, dan rendering system.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact