Menu
CoddyTech

Pola Decorator

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan PHP di Coddy. Pelajaran 77 dari 91.

Decorator Pattern adalah pola desain struktural yang memungkinkan kamu menambahkan perilaku baru ke object secara dinamis dengan membungkusnya dalam object pembungkus khusus yang disebut decorator. Tidak seperti pewarisan, yang menambahkan perilaku saat kompilasi, decorator menambahkan perilaku saat runtime.

Bayangkan sebuah kedai kopi. Kamu mulai dengan kopi dasar, lalu menambahkan pelengkap seperti susu, gula, atau krim kocok.

Setiap tambahan membungkus kopi asli dan menambahkan deskripsi serta biayanya. Inti utamanya adalah kopi dasar dan dekorator menggunakan antarmuka yang sama.

<?php
interface Coffee {
    public function getDescription(): string;
    public function getCost(): float;
}

class SimpleCoffee implements Coffee {
    public function getDescription(): string {
        return "Simple Coffee";
    }
    
    public function getCost(): float {
        return 2.00;
    }
}

Decorator menerapkan antarmuka yang sama dan membungkus object Coffee lain:

<?php
class MilkDecorator implements Coffee {
    public function __construct(private Coffee $coffee) {}
    
    public function getDescription(): string {
        return $this->coffee->getDescription() . ", Milk";
    }
    
    public function getCost(): float {
        return $this->coffee->getCost() + 0.50;
    }
}

class SugarDecorator implements Coffee {
    public function __construct(private Coffee $coffee) {}
    
    public function getDescription(): string {
        return $this->coffee->getDescription() . ", Sugar";
    }
    
    public function getCost(): float {
        return $this->coffee->getCost() + 0.25;
    }
}

$coffee = new SimpleCoffee();
$coffee = new MilkDecorator($coffee);
$coffee = new SugarDecorator($coffee);

echo $coffee->getDescription() . " = $" . $coffee->getCost();

Output:

Simple Coffee, Milk, Sugar = $2.75

Setiap decorator membungkus object sebelumnya, membentuk rantai. Pola ini memungkinkan kamu menggabungkan berbagai perilaku dalam urutan dan jumlah apa pun tanpa membuat class untuk setiap kombinasi yang mungkin. Butuh dua porsi susu? Bungkus saja dua kali.

challenge icon

Tantangan

Mudah

Mari kita buat sistem pemesanan pizza menggunakan Decorator Pattern. Kamu akan memulai dengan pizza dasar, lalu menambahkan topping secara dinamis: setiap topping membungkus pizza dan menambahkan deskripsi serta harganya, seperti contoh kopi dalam pelajaran.

Kamu akan menyusun kodemu dalam empat file:

  • Pizza.php: Definisikan interface Pizza yang menetapkan kontrak untuk semua pizza dan topping. Interface ini harus memiliki dua method: getDescription(): string dan getPrice(): float.
  • BasePizza.php: Sertakan interface Pizza dan buat class MargheritaPizza yang mengimplementasikannya. Ini adalah pizza dasarmu dengan deskripsi "Margherita" dan harga 8.00.
  • Toppings.php: Sertakan interface Pizza dan buat tiga class dekorator yang mengimplementasikannya. Setiap dekorator membungkus object Pizza (terima object tersebut di constructor) dan menambahkan deskripsi serta harga:
    • CheeseTopping: Menambahkan ", Extra Cheese" ke deskripsi dan 1.50 ke harga
    • PepperoniTopping: Menambahkan ", Pepperoni" ke deskripsi dan 2.00 ke harga
    • MushroomTopping: Menambahkan ", Mushrooms" ke deskripsi dan 1.25 ke harga
  • main.php: Sertakan file BasePizza dan Toppings. Kamu akan menerima satu input: list topping yang dipisahkan dengan koma untuk ditambahkan (misalnya, "cheese,pepperoni" atau "mushroom,cheese,cheese").

    Mulailah dengan MargheritaPizza. Untuk setiap topping dalam input, bungkus pizzamu dengan dekorator yang sesuai:

    • "cheese" dibungkus dengan CheeseTopping
    • "pepperoni" dibungkus dengan PepperoniTopping
    • "mushroom" dibungkus dengan MushroomTopping

    Setelah menerapkan semua topping, cetak deskripsi dan harga akhir pizza dengan format ini:

    [description] = $[price]

    Format harga hingga dua angka desimal.

Perhatikan bahwa topping yang sama dapat diterapkan beberapa kali: memesan keju ekstra berarti membungkusnya dengan CheeseTopping dua kali. Inilah keunggulan Decorator Pattern!

Coba sendiri

<?php
require_once 'BasePizza.php';
require_once 'Toppings.php';

// Baca input berupa list topping yang dipisahkan koma
$input = trim(fgets(STDIN));
$toppings = explode(',', $input);

// Mulai dengan MargheritaPizza sebagai dasar
$pizza = new MargheritaPizza();

// TODO: Ulangi setiap topping dan bungkus pizza dengan decorator yang sesuai
// - "cheese" -> bungkus dengan CheeseTopping
// - "pepperoni" -> bungkus dengan PepperoniTopping
// - "mushroom" -> bungkus dengan MushroomTopping

// TODO: Cetak hasil dalam format: [description] = $[price]
// Format harga menjadi 2 angka di belakang koma menggunakan number_format()

?>
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 PHP online