GoF Creational: Factory Method, Abstract Factory, Builder, dan Singleton beserta kritiknya — dengan factory provider NestJS untuk koneksi DB, builder konstruksi payload Fiber, dan Eloquent Factory plus Manager driver Laravel — ditutup notification sender multi-channel di 3 stack

Kelompok pertama katalog Gang of Four menjawab satu pertanyaan: bagaimana membuat objek dengan benar — ketika konstruksinya kompleks, bervariasi menurut konteks, atau harus tunggal. Empat pattern yang dibahas hari ini (Factory Method, Abstract Factory, Builder, Singleton) adalah yang paling sering kalian temui di framework modern, sering kali tanpa disadari.
Definisikan antarmuka untuk membuat objek, biarkan subclass/provider memutuskan class konkretnya:
@Module({
providers: [
{
provide: 'DB_CONNECTION',
useFactory: async (config: ConfigService) => {
const client = new PrismaClient({ datasources: { db: { url:
config.get('DATABASE_URL') } } });
await client.$connect(); // async init di sini
return client;
},
inject: [ConfigService], // dependency factory
},
],
})
export class DatabaseModule {}
// Konsumen:
constructor(@Inject('DB_CONNECTION') private db: PrismaClient) {}Factory menyembunyikan detail konstruksi (async connect, parsing config) dari seluruh aplikasi.
Pabrik yang menghasilkan keluarga objek yang saling terkait:
type NotifierFactory interface {
Sender() Sender // cara kirim
Formatter() Formatter // bentuk pesan
}
type SlackFamily struct{}
func (SlackFamily) Sender() Sender { return slackSender{} }
func (SlackFamily) Formatter() Formatter { return markdownFormatter{} }
type EmailFamily struct{}
func (EmailFamily) Sender() Sender { return smtpSender{} }
func (EmailFamily) Formatter() Formatter { return htmlFormatter{} }
// Konsistensi terjamin: tak mungkin HTML formatter + Slack sender campur aduk.Memecah konstruksi objek kompleks menjadi langkah-langkah yang bisa dirangkai:
type WebhookPayload struct {
Event string; Data map[string]any
Signature string; Retries int
}
type PayloadBuilder struct{ p WebhookPayload }
func NewWebhook(event string) *PayloadBuilder {
return &PayloadBuilder{p: WebhookPayload{Event: event, Retries: 3}}
}
func (b *PayloadBuilder) With(data map[string]any) *PayloadBuilder {
b.p.Data = data; return b
}
func (b *PayloadBuilder) SignedWith(sig string) *PayloadBuilder {
b.p.Signature = sig; return b
}
func (b *PayloadBuilder) Build() WebhookPayload { return b.p }Singleton menjamin satu instance global. Masalahnya terkenal: state global tersembunyi, sulit dites (mock butuh reset), coupling tersembunyi, dan bahaya concurrency. Kabar baiknya: DI container adalah singleton yang benar — framework modern (NestJS providers default, Laravel singleton binding) memberikan jaminan instance-tunggal TANPA pola global. Kesimpulan praktis: di ekosistem ber-DI, hampir tidak perlu menulis Singleton manual.
$this->app->singleton(PaymentGatewayManager::class);Dua contoh yang wajib kalian kenali karena ada di framework secara native:
User::factory()->count(10)->create()) — Builder + Factory untuk seeding/testing.MailManager, FilesystemManager) — Factory Method produksi: Mail::driver('ses') mengembalikan transport berbeda lewat satu pintu.Target outline: bangun notification sender multi-channel dengan Abstract Factory di 3 stack.
interface NotificationFactory {
sender(): NotificationSender;
template(name: string): TemplateRenderer;
}
@Injectable()
export class SmsNotification implements NotificationFactory {
sender(): NotificationSender { return this.smsApi; }
template(name: string): TemplateRenderer { return new PlainText(name); }
constructor(private smsApi: SmsApiClient) {}
}
// Daftarkan per channel, pilih runtime by user preference.Uji hasil latihan: tambahkan channel baru (mis. WhatsApp) tanpa mengubah kode pemanggil — hanya factory/family baru didaftarkan.
Tip
Jangan hafal UML pattern — hafalkan masalah yang dipecahkan. Kalau bisa menjawab "masalah konstruksi apa yang muncul?", pattern akan datang sendiri saat dibutuhkan.
Rangkuman episode ini:
useFactory); Abstract Factory menjamin keluarga konsisten; Builder merangkai konstruksi bertahap.Episode 6 naik ke kelompok Structural: Adapter, Facade, Decorator, Proxy — termasuk kenapa interceptor NestJS dan middleware Laravel/Fiber sebenarnya adalah Decorator. Sampai jumpa!