Pola State
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 100 dari 104.
Pola State memungkinkan sebuah object mengubah perilakunya saat state internalnya berubah, sehingga object tersebut tampak seolah-olah berubah class. Alih-alih menggunakan pernyataan percabangan yang rumit untuk menangani berbagai state, kamu mengenkapsulasi setiap state sebagai class terpisah.
Pola ini terdiri dari Context yang menyimpan referensi ke state saat ini, State interface yang mendefinisikan perilaku khusus untuk setiap state, dan Concrete States yang menerapkan perilaku untuk setiap state:
#include <iostream>
#include <memory>
class Document; // Deklarasi awal
// Antarmuka State
class DocumentState {
public:
virtual void publish(Document& doc) = 0;
virtual std::string getName() const = 0;
virtual ~DocumentState() = default;
};
// Konteks
class Document {
std::unique_ptr<DocumentState> state;
public:
Document();
void setState(std::unique_ptr<DocumentState> newState) {
state = std::move(newState);
}
void publish() { state->publish(*this); }
std::string getStateName() const { return state->getName(); }
};
// State konkret
class Draft : public DocumentState {
public:
void publish(Document& doc) override;
std::string getName() const override { return "Draft"; }
};
class Review : public DocumentState {
public:
void publish(Document& doc) override;
std::string getName() const override { return "Review"; }
};
class Published : public DocumentState {
public:
void publish(Document& doc) override {
std::cout << "Already published\n";
}
std::string getName() const override { return "Published"; }
};
void Draft::publish(Document& doc) {
std::cout << "Moving to review\n";
doc.setState(std::make_unique<Review>());
}
void Review::publish(Document& doc) {
std::cout << "Publishing document\n";
doc.setState(std::make_unique<Published>());
}
Document::Document() : state(std::make_unique<Draft>()) {}Setiap state menangani aksi publish() dengan cara yang berbeda dan bertanggung jawab untuk beralih ke state berikutnya. Document tidak perlu mengetahui logika transisi, Document hanya meneruskannya ke state saat ini. Ini menghilangkan pernyataan switch yang besar dan memudahkan penambahan state baru.
Gunakan State saat perilaku object sangat bergantung pada statusnya dan kamu memiliki banyak pernyataan percabangan yang memilih berdasarkan status object.
Tantangan
MudahMari buat Pengendali Lampu Lalu Lintas menggunakan pola State. Kamu akan membuat sistem yang membuat lampu lalu lintas berputar melalui berbagai state (Red, Yellow, Green), dengan setiap state menentukan apa yang terjadi saat lampu berubah dan pesan apa yang ditampilkan. Ini adalah contoh klasik pola State: perilaku lampu lalu lintas sepenuhnya bergantung pada state-nya saat ini.
Kamu akan menyusun kodemu dalam tiga file:
TrafficLightState.h: Definisikan antarmuka state dan semua class state konkret.Buat class abstrak
TrafficLightStatedengan:- method virtual murni
change(TrafficLight& light)yang menangani perpindahan ke state berikutnya - method virtual murni
getColor()yang mengembalikan warna saat ini sebagai string - method virtual murni
getAction()yang mengembalikan tindakan yang harus dilakukan pengemudi (misalnya, "Stop", "Caution", "Go") - destruktor virtual
Implementasikan tiga state konkret:
RedState: warnanya"Red", tindakannya"Stop", berubah menjadi GreenYellowState: warnanya"Yellow", tindakannya"Caution", berubah menjadi RedGreenState: warnanya"Green", tindakannya"Go", berubah menjadi Yellow
Kamu memerlukan deklarasi awal untuk
TrafficLightkarena state-state tersebut merujuknya.- method virtual murni
TrafficLight.h: Buat class konteks yang mempertahankan state saat ini.Class
TrafficLightmilikmu harus menyimpanstd::unique_ptr<TrafficLightState>dan secara default dimulai dalam state Red. Implementasikan:setState(std::unique_ptr<TrafficLightState> newState): mengubah state saat inichange(): meneruskan pemanggilan ke method change pada state saat inidisplay(): mencetak status lampu dengan format:[Color]: [Action]
main.cpp: Tunjukkan lampu lalu lintas yang berputar melalui berbagai state.Baca satu input: jumlah perubahan state yang harus dilakukan (bilangan bulat).
Buat
TrafficLightdan tampilkan state awalnya. Kemudian lakukan jumlah perubahan yang ditentukan, dengan menampilkan state setelah setiap perubahan.
Contohnya, dengan input 3:
Red: Stop
Green: Go
Yellow: Caution
Red: StopDengan input 6:
Red: Stop
Green: Go
Yellow: Caution
Red: Stop
Green: Go
Yellow: Caution
Red: StopPerhatikan bagaimana lampu lalu lintas berputar melalui state-state-nya dalam pola yang dapat diprediksi: Red → Green → Yellow → Red. Setiap state mengetahui state mana yang berikutnya dan menangani transisinya sendiri. Class TrafficLight tidak memerlukan logika percabangan untuk menentukan apa yang terjadi. Class tersebut cukup meneruskan pemanggilan ke state yang sedang aktif.
Coba sendiri
#include <iostream>
#include "TrafficLight.h"
using namespace std;
int main() {
// Baca jumlah perubahan status
int numChanges;
cin >> numChanges;
// TODO: Buat object TrafficLight
// TODO: Tampilkan status awal
// TODO: Lakukan perubahan sebanyak jumlah yang ditentukan
// Setelah setiap perubahan, tampilkan status saat ini
return 0;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar-Dasar OOP
File EksternalBuild dan Kompilasi C++File Header dan File SourceNamespace dan CakupanPengantar OOP dalam C++class vs objectPointer 'this'method (Fungsi Anggota)Atribut (Anggota Data)Dasar Ctor dan DtorRingkasan: Kalkulator Sederhana4Properti class
Anggota instance vs staticGetter dan setterFungsi anggota constKata kunci mutableMethod dan variabel staticFungsi dan class friendRangkuman, Pengelola Rekening Bank7Pewarisan
Pewarisan DasarTingkat Akses pada PewarisanUrutan Pemanggilan Ctor & DtorPenimpaan methodFungsi Virtual & VTablePewarisan BergandaPewarisan VirtualRangkuman: Hierarki Karyawan2Manajemen Memori
Memori Stack vs HeapPointer dan ReferenceMemori Dinamis (new/delete)Smart Pointer di C++RAII di C++Rangkuman: Pengelola Array Dinamis5Enkapsulasi
Penentu Akses dalam C++Penentu Akses secara MendalamPenyembunyian Informasistruct vs classNested dan Inner classRangkuman, Sistem Catatan Siswa8Polimorfisme
Polimorfisme saat Compile vs RuntimeOverloading FungsiMeninjau Kembali Fungsi VirtualFungsi Virtual MurniKelas AbstrakDesain Interface di C++Casting Dinamis & RTTIRangkuman: Kalkulator Bentuk11Konsep OOP Lanjutan
Komposisi vs PewarisanMixin melalui CRTPIdiom PimplPenghapusan TipeKelas Enum dan Pengetikan KuatPenanganan Pengecualian dalam OOPHierarki Pengecualian Kustom14Pola Desain Bagian 2
Pola CommandPola AdapterPola DecoratorPola Template MethodPola StatePola CompositeRAII sebagai Pola3Konstruktor & Destruktor
Konstruktor DefaultKonstruktor BerparameterKonstruktor SalinKonstruktor PindahDaftar Inisialisasi KonstruktorKonstruktor DelegasiKupas Tuntas DestruktorAturan Tiga, Lima, dan NolRangkuman: class String6Overloading Operator
Pengantar Overloading OperatorOverloading Operator AritmetikaOverloading Operator PerbandinganOperator StreamOverloading Operator PenugasanOverloading Operator [] dan ()Operator Konversi TipeRingkasan, class Matrix9Template
Template FungsiTemplate classSpesialisasi TemplateTemplate VariadikDasar SFINAE & Type TraitsRangkuman, Container GenerikLatihan sendiri: Compiler C++ online