Factory Pattern

Apa Itu Factory Pattern?

Factory Pattern pada dasarnya adalah cara untuk membuat objek tanpa harus mengetahui secara detail bagaimana objek tersebut dibuat. Bayangkan seperti ini:

  • Anda tidak perlu tahu cara membuat mobil dari nol

  • Anda hanya perlu pergi ke dealer dan mengatakan "saya mau mobil"

  • Dealer (factory) akan membuatkan mobil untuk Anda

Dalam pemrograman, Factory Pattern melakukan hal yang sama: menyediakan fungsi khusus (factory function) yang akan membuat objek untuk kita.

Contoh Analogi Dunia Nyata

Tanpa Factory Pattern:

// Kita harus tahu cara membuat setiap objek secara manual
func main() {
    // Harus tahu detail cara membuat mobil
    car := Car{model: "Toyota", year: 2023}
    
    // Harus tahu detail cara membuat motor
    bike := Bike{type: "Sport", cc: 150}
}

Dengan Factory Pattern:

// Kita cukup panggil factory function
func main() {
    // Tidak perlu tahu detail pembuatan
    car, _ := NewVehicle("car")
    bike, _ := NewVehicle("bike")
}

Konsep Inti Factory Pattern di Go

Di Go, Factory Pattern memiliki 3 konsep penting:

1. Interface (Kontrak)

type Vehicle interface {
    Move() string
}

Ini adalah "kontrak" yang menjamin semua kendaraan punya method Move().

2. Implementasi Konkret

type Car struct{}
func (c Car) Move() string { return "Mobil berjalan" }

type Bike struct{}
func (b Bike) Move() string { return "Motor berjalan" }

Ini adalah implementasi spesifik dari interface.

3. Factory Function (Pabrik)

func NewVehicle(tipe string) (Vehicle, error) {
    switch tipe {
    case "car":
        return Car{}, nil
    case "bike":
        return Bike{}, nil
    default:
        return nil, fmt.Errorf("Tipe kendaraan tidak dikenal")
    }
}

Ini adalah "pabrik" yang membuat objek sesuai permintaan.

Mengapa Ini Berguna?

1. Enkapsulasi Logika Pembuatan

// Tanpa Factory
func createCar() Car {
    // Logika kompleks untuk membuat mobil
    // Bisa jadi 100 baris kode
    return Car{...}
}

// Dengan Factory
car, _ := NewVehicle("car") // Satu baris saja

2. Fleksibilitas dalam Mengganti Implementasi

// Kita bisa ganti implementasi Car tanpa mengubah kode client
type ElectricCar struct{}
func (e ElectricCar) Move() string { return "Mobil listrik berjalan" }

// Cukup ubah di factory
func NewVehicle(tipe string) (Vehicle, error) {
    switch tipe {
    case "car":
        return ElectricCar{}, nil // Ganti implementasi di sini
    // ...
    }
}

3. Memudahkan Testing

// Dalam testing, kita bisa pakai mock
type MockVehicle struct{}
func (m MockVehicle) Move() string { return "Mock bergerak" }

func TestDelivery(t *testing.T) {
    // Ganti factory dengan mock
    originalFactory := NewVehicle
    NewVehicle = func(tipe string) (Vehicle, error) {
        return MockVehicle{}, nil
    }
    
    // Jalankan test...
    
    // Kembalikan factory asli
    NewVehicle = originalFactory
}

Perbandingan dengan Terminologi OOP Tradisional

Istilah OOP tradisional
Ekuivalen di Go

Superclass

Interface

Subclass

Struct yang mengimplementasi interface

Method overriding

Implementasi method pada struct

Constructor

Factory function

Kesimpulan

Factory Pattern di Go bukan tentang "subclass yang mengubah tipe objek", melainkan tentang:

  1. Menyediakan fungsi khusus (factory function) untuk membuat objek

  2. Mengembalikan interface bukan struct konkret

  3. Menyembunyikan detail implementasi dari kode yang menggunakan objek

  4. Memungkinkan perubahan implementasi tanpa mengubah kode client

Ini membuat kode lebih:

  • Modular: Logika pembuatan terpisah dari penggunaan

  • Fleksibel: Mudah mengganti implementasi

  • Testable: Mudah membuat mock untuk testing

  • Mudah dipahami: Kode client lebih sederhana

Dengan Factory Pattern, kita bisa fokus pada "apa" yang kita butuhkan (mobil, motor, dll) tanpa perlu pusing dengan "bagaimana" cara membuatnya.

Last updated