Durum Kalıbı
Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 74 / 87.
State Pattern (Durum Deseni), bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanıyan davranışsal bir tasarım desenidir. Nesne, sınıfını değiştiriyormuş gibi görünür; ancak gerçekte davranışı farklı durum nesnelerine devreder. Bir otomat makinesini düşünün: Bir düğmeye basılmasına verdiği yanıt; makinenin boşta olmasına, para atılmış olmasına veya bir ürün veriyor olmasına bağlı olarak değişir.
Farklı durumları yönetmek için karmaşık koşullu ifadeler kullanmak yerine, her durumu kendi sınıfı içinde kapsüllersiniz. Bu desen, mevcut duruma bir referans tutan bir Context ve her durum için davranışı tanımlayan State sınıflarını içerir:
interface State {
void handle(Context context);
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}Her bir somut durum davranışı uygular ve diğer durumlara geçişleri tetikleyebilir:
class IdleState implements State {
public void handle(Context context) {
System.out.println("Idle: Insert coin to start");
context.setState(new ActiveState());
}
}
class ActiveState implements State {
public void handle(Context context) {
System.out.println("Active: Processing...");
context.setState(new IdleState());
}
}Context, istekleri mevcut durumuna devreder ve durum değiştikçe davranış otomatik olarak değişir:
Context context = new Context();
context.setState(new IdleState());
context.request(); // Boşta: Başlamak için madeni para yerleştirin
context.request(); // Aktif: İşleniyor...State Deseni, bir nesnenin davranışı büyük ölçüde durumuna bağlı olduğunda ve çalışma zamanında değişmesi gerektiğinde idealdir. Büyük koşullu blokları ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır; sadece State arayüzünü uygulayan yeni bir sınıf oluşturmanız yeterlidir.
Görev
KolayState Pattern kullanarak bir belge iş akışı sistemi oluşturalım! Bir belgenin farklı aşamalardan (Draft, Review ve Published) nasıl geçtiğini modelleyen bir sistem oluşturacaksınız; her durum, hangi eylemlerin mevcut olduğunu ve belgeyi düzenlemeye veya onaylamaya çalıştığınızda belgenin nasıl davranacağını belirleyecektir.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
DocumentState.java: Tüm durumların uygulayacağıDocumentStatearayüzünü tanımlayın. İki yöntem bildirmelidir: belgeyi düzenlemeye çalışmak içinedit(Document doc)ve belgeyi onaylamak/bir sonraki aşamaya geçirmek içinapprove(Document doc).States.java:DocumentStatearayüzünü uygulayan üç somut durum sınıfı oluşturun:DraftState-editçağrıldığında,Editing draft...yazdırın.approveçağrıldığında,Draft approved. Moving to review.yazdırın ve belgeyiReviewStatedurumuna geçirin.ReviewState-editçağrıldığında,Cannot edit during review.yazdırın (durum değişikliği yok).approveçağrıldığında,Review complete. Publishing document.yazdırın vePublishedStatedurumuna geçirin.PublishedState-editçağrıldığında,Cannot edit published document.yazdırın.approveçağrıldığında,Document already published.yazdırın. Hiçbir eylem durumu değiştirmez.Document.java: Mevcut durumu koruyan bağlam (context) sınıfını oluşturun.Documentsınıfınız şunlara sahip olmalıdır:Mevcut
DocumentStatenesnesini tutan ve yapıcıda (constructor)DraftStateolarak başlatılan özel bir alan.Mevcut durumu değiştiren bir
setState(DocumentState state)yöntemi.Mevcut durumun
edityöntemine yetki devreden biredit()yöntemi.Mevcut durumun
approveyöntemine yetki devreden birapprove()yöntemi.Mevcut durumun basit sınıf adını döndüren bir
getStatus()yöntemi (getClass().getSimpleName()kullanın).Main.java: Durum sisteminizi gösterin! Bir girdi alacaksınız: her bir eylemineditveyaapproveolduğu virgülle ayrılmış bir dize (örneğin:edit,approve,edit,approve).Bir
Documentoluşturun ve başlangıç durumunuStatus: [state]formatında yazdırın. Ardından her eylemi sırayla işleyin ve belgedeki uygun yöntemi çağırın. Her eylemden sonra mevcut durumu yazdırın.
Bir girdi alacaksınız: virgülle ayrılmış bir eylem dizisi.
Örneğin, edit,approve,approve girdisi ile çıktınız şöyle olacaktır:
Status: DraftState
Editing draft...
Status: DraftState
Draft approved. Moving to review.
Status: ReviewState
Review complete. Publishing document.
Status: PublishedStateAynı approve() çağrısının belgenin mevcut durumuna bağlı olarak nasıl farklı sonuçlar ürettiğine dikkat edin; State Pattern'in özü budur! Belge, durumunu kontrol etmek için koşullu ifadeler kullanmaz; bunun yerine, davranışı eylemi uygun şekilde işleyen ve gerektiğinde geçişleri tetikleyen mevcut durum nesnesine devreder.
Kopya kağıdı
Durum Deseni (State Pattern), bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanıyan ve karmaşık koşullu ifadeler kullanmak yerine davranışı farklı durum nesnelerine devreden davranışsal bir tasarım desenidir.
Desen, mevcut duruma bir referans tutan bir Context ve her durum için davranışı tanımlayan State sınıflarından oluşur:
interface State {
void handle(Context context);
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}Her somut durum davranışı uygular ve diğer durumlara geçişleri tetikleyebilir:
class IdleState implements State {
public void handle(Context context) {
System.out.println("Idle: Insert coin to start");
context.setState(new ActiveState());
}
}
class ActiveState implements State {
public void handle(Context context) {
System.out.println("Active: Processing...");
context.setState(new IdleState());
}
}Context, istekleri mevcut durumuna devreder ve durum değiştikçe davranış otomatik olarak değişir:
Context context = new Context();
context.setState(new IdleState());
context.request(); // Idle: Insert coin to start
context.request(); // Active: Processing...Durum Deseni, bir nesnenin davranışının büyük ölçüde durumuna bağlı olduğu ve çalışma zamanında değişmesi gerektiği durumlar için idealdir. Büyük koşullu blokları ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır.
Kendin dene
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Yeni bir Document oluşturun
// TODO: Başlangıç durumunu "Status: [state]" formatında yazdırın
// TODO: Münferit eylemleri elde etmek için girişi virgüle göre bölün
// TODO: Her bir eylem üzerinde döngü kurun
// - Eğer eylem "edit" ise, belge üzerinde edit() metodunu çağırın
// - Eğer eylem "approve" ise, belge üzerinde approve() metodunu çağırın
// - Her eylemden sonra mevcut durumu yazdırın
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarAlanlar (Öznitelikler)Yapıcı MetotYapıcı Metot Aşırı YüklemeÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (extends)super Anahtar KelimesiMetot Geçersiz Kılma (@Override)Yapıcı Metot ZincirlemeObject SınıfıTekli ve Çok Seviyeli KalıtımNeden Çoklu Sınıf Kalıtımı Yok?Özet - Çalışan Hiyerarşisi7Özel Metotlar ve Object Sınıfı
toString() Metoduequals() ve hashCode()clone() MetoducompareTo() ve ComparableComparator ArayüzüÖzet - Özel Sıralama2Erişim Belirleyiciler ve Kapsülleme
Erişim Seviyelerine Genel BakışGetter ve Setter MetotlarıBilgi Gizlemefinal Anahtar KelimesiÖzet - Banka Hesabı Yöneticisi5Polimorfizm
Metot Aşırı Yükleme TemelleriMetot Geçersiz Kılma (Çalışma Zamanı)Upcasting ve Downcastinginstanceof OperatörüSoyut Sınıflar ve MetotlarÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımAgregasyon vs KompozisyonDahili, Yuvalanmış ve Anonim SınıflarEnum'lar ve Enum MetotlarıRecords (Java 16+)Sealed Classes (Java 17+)11Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıBuilder KalıbıObserver KalıbıStrategy Kalıbı14Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi3Sınıf Özellikleri ve Statik Üyeler
Instance ve Statik DeğişkenlerStatik MetotlarStatik BloklarSabitler (static final)Özet - Sayaç ve Utility6Arayüzler ve Soyut Sınıflar
Arayüzlere GirişArayüzleri UygulamaÇoklu Arayüz UygulamaArayüzlerde Default ve StaticSoyut Sınıflar ve ArayüzlerFonksiyonel ArayüzlerÖzet - Ödeme Sistemi9Generics
Generics'e GirişGeneric SınıflarGeneric MetotlarSınırlandırılmış Tip ParametreleriWildcard'lar (?, extends, super)Özet - Generic Container12Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıYineleyici Kalıbı