package main

import "fmt"

// Notifier adalah kontrak pengiriman pesan: cukup satu method.
type Notifier interface {
	Kirim(penerima, pesan string) string
}

// EmailNotifier dan SmsNotifier sama-sama kecil dan mudah diganti.
type EmailNotifier struct {
	Domain string
}

func (e EmailNotifier) Kirim(penerima, pesan string) string {
	return "email ke " + penerima + "@" + e.Domain + ": " + pesan
}

type SmsNotifier struct {
	Gerbang string
}

func (s SmsNotifier) Kirim(penerima, pesan string) string {
	return "sms via " + s.Gerbang + " ke " + penerima + ": " + pesan
}

// broadcast mendefinisikan Notifier di sisi pemakai, bukan di sisi implementasi.
func broadcast(n Notifier, penerima []string, pesan string) {
	for _, p := range penerima {
		fmt.Println(n.Kirim(p, pesan))
	}
}

func main() {
	penerima := []string{"budi", "siti"}
	broadcast(EmailNotifier{Domain: "example.com"}, penerima, "server siap")
	broadcast(SmsNotifier{Gerbang: "gateway-1"}, penerima, "server siap")
}
