Pola Decorator
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Java di Coddy. Pelajaran 72 dari 87.
Decorator Pattern adalah pola desain struktural yang memungkinkan kamu menambahkan perilaku baru ke object dengan membungkusnya dalam object khusus yang disebut decorator. Berbeda dengan pewarisan, yang menambahkan perilaku saat kompilasi, decorator menambahkan fungsionalitas secara dinamis saat program berjalan tanpa mengubah class asli.
Bayangkan kedai kopi tempat kamu memulai dengan kopi dasar dan bisa menambahkan bahan tambahan seperti susu, gula, atau krim kocok. Setiap tambahan membungkus kopi asli, lalu menambahkan biaya dan deskripsinya. Pola ini menggunakan antarmuka umum agar object yang dihias dapat diperlakukan sama seperti object asli:
interface Coffee {
String getDescription();
double getCost();
}
class SimpleCoffee implements Coffee {
public String getDescription() {
return "Simple Coffee";
}
public double getCost() {
return 2.0;
}
}
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
public double getCost() {
return coffee.getCost() + 0.5;
}
}Decorator menyimpan referensi ke object yang dibungkus dan meneruskan pemanggilan kepadanya sambil menambahkan perilakunya sendiri. Kamu dapat menumpuk beberapa decorator untuk menggabungkan fitur:
Coffee order = new SimpleCoffee();
order = new MilkDecorator(order);
order = new SugarDecorator(order);
System.out.println(order.getDescription()); // Simple Coffee, Milk, Sugar
System.out.println(order.getCost()); // 2.75Decorator Pattern sangat berguna saat kamu perlu menambahkan tanggung jawab ke object tanpa membuat banyak sekali subclass. Setiap decorator bersifat independen, jadi kamu bisa menggabungkannya dengan bebas untuk menciptakan kombinasi perilaku yang kamu butuhkan.
Tantangan
MudahMari kita bangun sistem notifikasi menggunakan Decorator Pattern! Kamu akan membuat notifikasi dasar yang dapat ditingkatkan dengan berbagai saluran pengiriman, yaitu pemberitahuan email, pemberitahuan SMS, dan notifikasi push, dengan membungkus decorator satu sama lain. Ini mencerminkan sistem di dunia nyata, tempat satu pesan mungkin perlu dikirim melalui beberapa saluran sekaligus.
Kamu akan mengatur kodemu dalam empat file:
Notifier.java: Definisikan interfaceNotifieryang berfungsi sebagai interface komponen untuk decorator pattern-mu. Interface ini harus mendeklarasikan methodsend(String message)yang menangani pengiriman notifikasi.BasicNotifier.java: Buat class komponen konkret yang mengimplementasikanNotifier. Class ini merepresentasikan bentuk notifikasi paling sederhana, yaitu pemberitahuan dalam aplikasi. Saatsenddipanggil, class ini harus mencetakIn-App: [message].NotifierDecorators.java: Bangun hierarki decorator-mu di sini. Mulailah dengan class abstrakNotifierDecoratoryang mengimplementasikanNotifierdan menyimpan referensi ke objectNotifieryang dibungkus (diberikan melalui konstruktornya).Lalu, buat tiga decorator konkret yang memperluas
NotifierDecorator:EmailDecorator- Saatsenddipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetakEmail: [message].SMSDecorator- Saatsenddipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetakSMS: [message].PushDecorator- Saatsenddipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetakPush: [message].Main.java: Gabungkan sistem decorator-mu! Kamu akan menerima dua input: pesan notifikasi (String) dan daftar saluran yang dipisahkan dengan koma untuk ditambahkan (String), misalnya"email,sms"atau"push,email,sms".Mulailah dengan
BasicNotifier. Lalu, berdasarkan input saluran, bungkus notifier tersebut dengan decorator yang sesuai sesuai urutan kemunculannya. Nama saluran yang valid adalahemail,sms, danpush.Terakhir, panggil
senddengan pesanmu pada notifier yang sudah sepenuhnya dibungkus decorator.
Kamu akan menerima dua input secara berurutan: pesan yang akan dikirim (String) dan saluran yang akan diaktifkan (String, dipisahkan dengan koma).
Misalnya, dengan input Server is down! dan email,push, output-mu akan menjadi:
In-App: Server is down!
Email: Server is down!
Push: Server is down!Perhatikan bagaimana setiap decorator menambahkan perilakunya sendiri sambil mempertahankan notifikasi asli. Urutan pembungkusan menentukan urutan output: komponen paling dalam (BasicNotifier) dijalankan terlebih dahulu, lalu setiap decorator menambahkan lapisannya. Kamu dapat memadukan kombinasi saluran apa pun tanpa membuat class terpisah untuk setiap kombinasi!
Coba sendiri
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Baca pesan yang akan kamu kirim
String message = scanner.nextLine();
// Baca list channel yang dipisahkan dengan koma (misalnya, "email,sms" atau "push,email,sms")
String channelsInput = scanner.nextLine();
// TODO: Mulai dengan BasicNotifier
// TODO: Pisahkan input channel berdasarkan koma
// TODO: Ulangi untuk setiap channel dan bungkus notifier dengan decorator yang sesuai
// Channel yang valid adalah: "email", "sms", "push"
// TODO: Panggil send pada notifier yang sudah dibungkus sepenuhnya dengan pesan tersebut
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP
File EksternalPengantar OOPClass dan ObjectKata Kunci thisMethodField (Atribut)Method KonstruktorOverloading KonstruktorRangkuman: Kalkulator Sederhana4Pewarisan
Pewarisan Dasar (extends)Kata Kunci superMethod Overriding (@Override)Rantai KonstruktorKelas ObjectPewarisan Tunggal dan BertingkatMengapa Tidak Ada Pewarisan Multi-KelasRangkuman: Hierarki Karyawan7method Khusus & class Object
method toString()equals() dan hashCode()method clone()compareTo() dan ComparableAntarmuka ComparatorUlasan: Pengurutan Kustom10Penanganan Exception dalam OOP
Hierarki class ExceptionException KustomError Checked vs UncheckedPola Try-with-ResourcesRekap: Pengguna Tervalidasi2Modifier Akses & Enkapsulasi
Ikhtisar Tingkat AksesMethod Getter dan SetterPenyembunyian InformasiKata Kunci finalUlasan: Pengelola Rekening Bank5Polimorfisme
Dasar method overloadingMethod overriding (Saat program berjalan)Upcasting dan downcastingOperator instanceofclass dan method abstrakUlasan: Kalkulator Bentuk8Konsep OOP Lanjutan
Komposisi vs PewarisanAgregasi vs Komposisiinner, nested, dan anonymous classEnum dan method Enumrecord (Java 16+)sealed class (Java 17+)11Pola Desain Bagian 1
Pengantar Pola DesainPola SingletonPola FactoryPola BuilderPola ObserverPola Strategy3property class dan Anggota Statis
Variabel Instance vs Statismethod StatisBlok StatisKonstanta (static final)Rangkuman: Penghitung dan Utilitas6Antarmuka & Kelas Abstrak
Pengantar AntarmukaMengimplementasikan AntarmukaImplementasi Beberapa AntarmukaDefault & Static pada AntarmukaKelas Abstrak vs AntarmukaAntarmuka FungsionalRekap: Sistem Pembayaran9Generik
Pengantar GenerikClass GenerikMethod GenerikParameter Tipe BerbatasWildcard (?, extends, super)Ulasan: Wadah Generik12Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositePola IteratorLatihan sendiri: Compiler Java online