Prototype Pattern #

Dalam pengembangan perangkat lunak, pembuatan objek adalah hal yang sering ditemui. Namun, tidak semua objek dibuat dengan cara yang sederhana. Beberapa objek memiliki konfigurasi yang kompleks atau membutuhkan resource yang mahal untuk dibuat. Di sinilah Prototype Pattern hadir sebagai solusi: memungkinkan pengembang untuk membuat salinan objek yang sudah ada (clone), sehingga menghemat waktu dan sumber daya.

Prototype Pattern termasuk dalam kategori Creational Design Pattern, yang fokus pada cara membuat objek. Dengan menggunakan prototype, pengembang tidak perlu mengetahui detail implementasi kelas konkret; cukup menyalin objek yang sudah ada dan melakukan modifikasi seperlunya. Pendekatan ini sangat berguna untuk objek yang kompleks, memiliki banyak variasi, atau harus dibuat secara dinamis saat runtime.

Dengan memahami konsep, tujuan, dan penerapan Prototype Pattern, pengembang dapat menciptakan sistem yang lebih efisien, fleksibel, dan mudah dirawat.

Apa itu Prototype Pattern? #

Prototype Pattern adalah salah satu creational design pattern yang berfokus pada pembuatan objek baru dengan cara meng-clone objek yang sudah ada, bukan membuatnya dari nol menggunakan constructor.

Inti idenya sederhana:

Jika biaya atau kompleksitas pembuatan sebuah objek mahal, maka lebih efisien untuk menduplikasi objek yang sudah ada.

Alih-alih memanggil new atau constructor berkali-kali, sistem menyimpan sebuah prototype (contoh objek), lalu membuat objek baru dengan cara menyalinnya.

Tujuan Pattern #

Prototype Pattern digunakan untuk:

  1. Mengurangi biaya pembuatan objek Cocok untuk objek yang mahal dibuat (misalnya: banyak konfigurasi, parsing data besar, atau setup kompleks).

  2. Menghindari ketergantungan ke kelas konkret Klien tidak perlu tahu kelas konkret objek, cukup tahu bahwa objek tersebut bisa di-clone.

  3. Menyederhanakan pembuatan variasi objek Dengan satu prototype dasar, kita bisa membuat banyak variasi dengan sedikit modifikasi.

  4. Mendukung runtime object creation Prototype bisa diregistrasikan atau dimodifikasi saat aplikasi berjalan.


Kapan Cocok Digunakan? #

Prototype Pattern sangat cocok digunakan ketika:

  • Pembuatan objek mahal atau kompleks
  • Banyak objek memiliki struktur mirip
  • Ingin menghindari subclass explosion (terlalu banyak turunan kelas)
  • Objek perlu dibuat berdasarkan state runtime, bukan compile-time
  • Sistem membutuhkan copy objek yang aman (deep copy)

Contoh use case nyata #

  • Konfigurasi service atau client SDK
  • Template dokumen
  • Game object (NPC, senjata, item)
  • Snapshot / state cloning
  • Object pool dengan state awal tertentu

Struktur Pattern #

Secara konseptual, Prototype Pattern terdiri dari:

  1. Prototype interface → mendefinisikan method Clone()
  2. Concrete Prototype → implementasi clone (shallow / deep)
  3. Client → menggunakan clone tanpa tahu detail kelas

Contoh Implementasi (Golang) #

Go tidak memiliki konsep clone() bawaan atau copy constructor, sehingga Prototype Pattern di Go biasanya diimplementasikan menggunakan:

  • Interface dengan method Clone()
  • Copy struct secara manual
  • Kombinasi shallow dan deep copy

Contoh Kasus #

Misalkan kita memiliki objek konfigurasi service yang mahal dibuat.


Definisikan Interface Prototype #

type Prototype interface {
    Clone() Prototype
}

Concrete Prototype #

type ServiceConfig struct {
    Name       string
    Timeout    int
    Headers    map[string]string
}

func (s *ServiceConfig) Clone() Prototype {
    // deep copy untuk map
    headersCopy := make(map[string]string)
    for k, v := range s.Headers {
        headersCopy[k] = v
    }

    return &ServiceConfig{
        Name:    s.Name,
        Timeout: s.Timeout,
        Headers: headersCopy,
    }
}

⚠️ Penting: map dan slice harus di-deep copy, jika tidak akan berbagi reference.

Penggunaan di Client #

func main() {
    defaultConfig := &ServiceConfig{
        Name:    "payment-service",
        Timeout: 30,
        Headers: map[string]string{
            "Authorization": "Bearer token",
        },
    }

    clonedConfig := defaultConfig.Clone().(*ServiceConfig)
    clonedConfig.Timeout = 60
    clonedConfig.Headers["X-Env"] = "staging"

    // defaultConfig tetap aman
}

Shallow Copy vs Deep Copy #

Ini aspek paling krusial dalam Prototype Pattern.

Shallow Copy #

  • Menyalin field primitive
  • Reference (map, slice, pointer) dibagi

Risiko:

  • Perubahan di clone memengaruhi prototype

Deep Copy #

  • Semua reference dibuat ulang
  • Aman untuk stateful object

Rekomendasi:

Gunakan deep copy kecuali Anda benar-benar paham konsekuensinya.


Prototype Registry (Advanced) #

Dalam sistem besar, prototype sering disimpan dalam registry.

type PrototypeRegistry struct {
    prototypes map[string]Prototype
}

func NewRegistry() *PrototypeRegistry {
    return &PrototypeRegistry{
        prototypes: make(map[string]Prototype),
    }
}

func (r *PrototypeRegistry) Register(name string, p Prototype) {
    r.prototypes[name] = p
}

func (r *PrototypeRegistry) Create(name string) Prototype {
    if p, ok := r.prototypes[name]; ok {
        return p.Clone()
    }
    return nil
}

Use case:

  • Plugin system
  • Multi-tenant config
  • Runtime template

Kelebihan dan Kekurangan #

Kelebihan #

  • Performa lebih baik untuk objek kompleks
  • Fleksibel dan extensible
  • Mengurangi coupling

Kekurangan #

  • Implementasi clone bisa rumit
  • Risiko bug jika deep copy tidak sempurna
  • Tidak selalu intuitif untuk developer baru

Best Practices #

✅ Gunakan untuk objek mahal #

Jika object creation murah, Prototype Pattern justru menambah kompleksitas.

✅ Dokumentasikan strategi copy #

Jelaskan dengan jelas apakah Clone():

  • shallow
  • deep
  • hybrid

Ini sangat penting untuk tim.

❌ Hindari clone buta #

Jangan clone object besar tanpa alasan yang jelas.

✅ Lindungi prototype #

Prototype sebaiknya:

  • immutable, atau
  • tidak digunakan langsung oleh client

✅ Kombinasikan dengan pattern lain #

Prototype sering dipakai bersama:

  • Factory Pattern → factory mengembalikan clone
  • Builder Pattern → prototype sebagai base object
  • Object Pool → clone state awal

Penutup #

Prototype Pattern adalah solusi elegan ketika:

  • Object creation mahal
  • Banyak objek mirip
  • Dibutuhkan fleksibilitas runtime

Namun, pattern ini bukan default choice. Gunakan dengan sadar, pahami shallow vs deep copy, dan dokumentasikan dengan baik.

Jika digunakan dengan tepat, Prototype Pattern bisa secara signifikan meningkatkan performa dan maintainability sistem Anda.

“Clone objects when creation is expensive, not when thinking is cheap.”

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