import java.util.ArrayList;
import java.util.List;

// Kontrak penyimpanan: konsumen bergantung pada interface, bukan class konkret.
interface PenyimpananBuku {
    void tambah(String judul);

    int jumlah();

    List<String> daftarJudul();
}

// Satu tanggung jawab: menyimpan data katalog.
class KatalogBuku implements PenyimpananBuku {
    private final List<String> judulBuku = new ArrayList<>();

    @Override
    public void tambah(String judul) {
        judulBuku.add(judul);
    }

    @Override
    public int jumlah() {
        return judulBuku.size();
    }

    @Override
    public List<String> daftarJudul() {
        return List.copyOf(judulBuku); // salinan beku: internal tetap tertutup
    }
}

// Satu tanggung jawab: memformat laporan; berkomposisi dengan interface.
class LaporanPerpustakaan {
    private final PenyimpananBuku penyimpanan;

    public LaporanPerpustakaan(PenyimpananBuku penyimpanan) {
        this.penyimpanan = penyimpanan;
    }

    public void cetak() {
        System.out.println("== Laporan Perpustakaan ==");
        System.out.println("Jumlah buku: " + penyimpanan.jumlah());
        for (String judul : penyimpanan.daftarJudul()) {
            System.out.println("  - " + judul);
        }
    }
}

// Satu tanggung jawab: mengirim pemberitahuan peminjaman.
class NotifikasiPeminjaman {
    public void kirim(String judul, String peminjam) {
        System.out.println("[notifikasi] Halo " + peminjam
                + ", buku \"" + judul + "\" siap diambil.");
    }
}

public class SesudahRefactor {
    public static void main(String[] args) {
        PenyimpananBuku katalog = new KatalogBuku();
        LaporanPerpustakaan laporan = new LaporanPerpustakaan(katalog);
        NotifikasiPeminjaman notifikasi = new NotifikasiPeminjaman();

        katalog.tambah("Java Dasar");
        katalog.tambah("Java Lanjutan");
        notifikasi.kirim("Java Dasar", "Budi");

        // Upaya mutasi dari luar kini ditolak: data internal terlindungi.
        try {
            katalog.daftarJudul().clear();
        } catch (UnsupportedOperationException e) {
            System.out.println("daftar internal terlindungi dari mutasi luar");
        }

        laporan.cetak();
    }
}
