public class KeterikatanVsInjeksi {

    public static void main(String[] args) {
        System.out.println("== Perakitan manual di dalam kelas (keterikatan erat) ==");
        LayananRapatKaku kaku = new LayananRapatKaku();
        kaku.kirim("Rapat sprint besok pukul 09.00");

        System.out.println();
        System.out.println("== Constructor injection: dependensi disuntikkan dari luar ==");
        LayananRapat viaEmail = new LayananRapat(new PengirimEmail());
        viaEmail.kirim("Rapat sprint besok pukul 09.00");

        LayananRapat viaSms = new LayananRapat(new PengirimSms());
        viaSms.kirim("Rapat sprint dibatalkan");

        System.out.println();
        System.out.println("== Ganti implementasi tanpa menyentuh LayananRapat ==");
        LayananRapat viaLog = new LayananRapat(new PengirimLog());
        viaLog.kirim("Notifikasi hanya untuk log internal");
    }
}

// Versi terikat erat: kelas merakit dependensinya sendiri dengan new,
// sehingga PengirimEmail tertanam dan sulit diganti atau diuji terpisah.
class LayananRapatKaku {

    void kirim(String pesan) {
        PengirimEmail pengirim = new PengirimEmail();
        pengirim.kirim(pesan);
    }
}

interface PengirimPesan {
    void kirim(String pesan);
}

class PengirimEmail implements PengirimPesan {
    @Override
    public void kirim(String pesan) {
        System.out.println("[Email] " + pesan);
    }
}

class PengirimSms implements PengirimPesan {
    @Override
    public void kirim(String pesan) {
        System.out.println("[SMS] " + pesan);
    }
}

class PengirimLog implements PengirimPesan {
    @Override
    public void kirim(String pesan) {
        System.out.println("[Log] " + pesan);
    }
}

// Versi lentur: dependensi masuk lewat konstruktor (injection point)
// dan disimpan final agar tidak bisa ditukar di tengah jalan.
class LayananRapat {

    private final PengirimPesan pengirim;

    LayananRapat(PengirimPesan pengirim) {
        this.pengirim = pengirim;
    }

    void kirim(String pesan) {
        pengirim.kirim(pesan);
    }
}
