Menu
CoddyTech

Pola State

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

State Pattern adalah pola desain perilaku yang memungkinkan sebuah object mengubah perilakunya saat status internalnya berubah. Alih-alih menggunakan percabangan yang rumit untuk menangani berbagai status, kamu mengenkapsulasi setiap status dalam class-nya sendiri dan mendelegasikan perilaku kepada object status saat ini.

Bayangkan mesin penjual otomatis. Mesin ini berperilaku berbeda bergantung pada apakah mesin sedang menunggu uang, sudah menerima pembayaran, atau sedang mengeluarkan produk.

Setiap state memiliki aturannya sendiri tentang tindakan yang diizinkan. State Pattern memodelkan hal ini dengan membuat class untuk setiap state.

<?php
interface OrderState {
    public function proceed(Order $order): string;
    public function getStatus(): string;
}

class PendingState implements OrderState {
    public function proceed(Order $order): string {
        $order->setState(new ProcessingState());
        return "Order moved to processing";
    }
    
    public function getStatus(): string {
        return "Pending";
    }
}

class ProcessingState implements OrderState {
    public function proceed(Order $order): string {
        $order->setState(new ShippedState());
        return "Order has been shipped";
    }
    
    public function getStatus(): string {
        return "Processing";
    }
}

class ShippedState implements OrderState {
    public function proceed(Order $order): string {
        return "Order already shipped";
    }
    
    public function getStatus(): string {
        return "Shipped";
    }
}

class context menyimpan referensi ke state saat ini dan mendelegasikan pemanggilan kepadanya:

<?php
class Order {
    private OrderState $state;
    
    public function __construct() {
        $this->state = new PendingState();
    }
    
    public function setState(OrderState $state): void {
        $this->state = $state;
    }
    
    public function proceed(): string {
        return $this->state->proceed($this);
    }
    
    public function getStatus(): string {
        return $this->state->getStatus();
    }
}

$order = new Order();
echo $order->getStatus() . "\n";
echo $order->proceed() . "\n";
echo $order->getStatus() . "\n";
echo $order->proceed() . "\n";
echo $order->getStatus();

Output:

Pending
Order moved to processing
Processing
Order has been shipped
Shipped

Pola State menghilangkan pernyataan switch yang bertele-tele dan membuat penambahan state baru menjadi mudah. Setiap class state bertanggung jawab untuk mengetahui state berikutnya, sehingga logikanya tetap teratur dan mudah dipelihara.

challenge icon

Tantangan

Mudah

Mari buat sistem alur kerja dokumen menggunakan State Pattern. Dokumen dalam sistem manajemen konten melewati beberapa tahap, yaitu draft, review, dan published. Setiap tahap memiliki aturan tersendiri tentang tindakan yang diizinkan dan hal yang terjadi saat kamu mencoba melanjutkan dokumen ke tahap berikutnya.

Kamu akan mengatur kodemu dalam empat file:

  • DocumentState.php: Definisikan interface DocumentState yang menetapkan kontrak untuk semua state dokumen. Interface ini harus memiliki dua method: publish(Document $document): string untuk mencoba melanjutkan dokumen ke tahap berikutnya, dan getStatus(): string untuk mengembalikan nama state saat ini.
  • States.php: Sertakan interface DocumentState dan buat tiga class state yang mengimplementasikannya:
    • DraftState: Saat publish() dipanggil, state dokumen berubah menjadi ReviewState dan mengembalikan "Document sent for review". Statusnya adalah "Draft".
    • ReviewState: Saat publish() dipanggil, state dokumen berubah menjadi PublishedState dan mengembalikan "Document published". Statusnya adalah "Under Review".
    • PublishedState: Saat publish() dipanggil, method ini mengembalikan "Document is already published" tanpa mengubah state. Statusnya adalah "Published".
  • Document.php: Sertakan file States dan buat class Document yang bertindak sebagai context. Dokumenmu harus:
    • Menerima judul di constructornya dan dimulai dalam state DraftState
    • Memiliki method setState(DocumentState $state): void untuk mengubah state saat ini
    • Memiliki method publish(): string yang meneruskan pemanggilan ke method publish() pada state saat ini
    • Memiliki method getStatus(): string yang mengembalikan status state saat ini
  • main.php: Sertakan file Document. Kamu akan menerima satu input: jumlah pemanggilan publish() pada dokumen.

    Buat Document dengan judul "My Article". Pertama, cetak status awal. Lalu, panggil publish() sebanyak jumlah yang ditentukan dan cetak hasil setiap pemanggilan pada baris baru. Terakhir, cetak status akhir.

    Format output:

    Status: [initial status]
    [publish result 1]
    [publish result 2]
    ...
    Status: [final status]

Setiap class state mengetahui state berikutnya dalam alur kerja, sehingga logika transisi tetap teratur dan mudah diubah. Untuk menambahkan state baru seperti "Archived", kamu cukup membuat class baru dan memperbarui transisi yang relevan.

Coba sendiri

<?php

require_once 'Document.php';

// Baca input, yaitu jumlah pemanggilan publish()
$n = intval(trim(fgets(STDIN)));

// TODO: Buat Document dengan judul "My Article"

// TODO: Cetak status awal dengan format: "Status: [status]"

// TODO: Panggil publish() sebanyak n kali dan cetak setiap hasil pada baris baru

// TODO: Cetak status akhir dengan format: "Status: [status]"

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