Menu
CoddyTech

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.75

Decorator 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.

challenge icon

Tantangan

Mudah

Mari 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 interface Notifier yang berfungsi sebagai interface komponen untuk decorator pattern-mu. Interface ini harus mendeklarasikan method send(String message) yang menangani pengiriman notifikasi.
  • BasicNotifier.java: Buat class komponen konkret yang mengimplementasikan Notifier. Class ini merepresentasikan bentuk notifikasi paling sederhana, yaitu pemberitahuan dalam aplikasi. Saat send dipanggil, class ini harus mencetak In-App: [message].
  • NotifierDecorators.java: Bangun hierarki decorator-mu di sini. Mulailah dengan class abstrak NotifierDecorator yang mengimplementasikan Notifier dan menyimpan referensi ke object Notifier yang dibungkus (diberikan melalui konstruktornya).

    Lalu, buat tiga decorator konkret yang memperluas NotifierDecorator:

    EmailDecorator - Saat send dipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetak Email: [message].

    SMSDecorator - Saat send dipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetak SMS: [message].

    PushDecorator - Saat send dipanggil, decorator ini terlebih dahulu meneruskan pemanggilan ke notifier yang dibungkus, lalu mencetak Push: [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 adalah email, sms, dan push.

    Terakhir, panggil send dengan 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
        
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Java online