Durum Kalıbı
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 95 / 107.
State deseni, bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanır ve nesne sınıfını değiştirmiş gibi görünür. Template Method algoritma adımlarını kontrol ederken State, duruma özgü davranışı ayrı nesneler içinde kapsüller ve geçerli duruma devreder.
Go'da bir durum arayüzü tanımlar ve farklı davranışları uygulayan somut durumlar oluştururuz:
type State interface {
Handle(d *Document) string
}
type Document struct {
state State
}
func (d *Document) SetState(s State) {
d.state = s
}
func (d *Document) Publish() string {
return d.state.Handle(d)
}Her durum ne olacağını ve sırada hangi durumun geleceğini belirler:
type DraftState struct{}
func (s DraftState) Handle(d *Document) string {
d.SetState(ModerationState{})
return "Draft submitted for moderation"
}
type ModerationState struct{}
func (s ModerationState) Handle(d *Document) string {
d.SetState(PublishedState{})
return "Moderation approved, now published"
}
type PublishedState struct{}
func (s PublishedState) Handle(d *Document) string {
return "Already published"
}Aynı yöntem çağrısı, geçerli duruma bağlı olarak farklı sonuçlar üretir:
doc := &Document{state: DraftState{}}
fmt.Println(doc.Publish()) // Taslak moderasyona gönderildi
fmt.Println(doc.Publish()) // Moderasyon onaylandı, şimdi yayınlandı
fmt.Println(doc.Publish()) // Zaten yayınlandıState, sipariş işleme iş akışları, kullanıcı arayüzü bileşenleri veya davranışın tamamen mevcut duruma bağlı olduğu bağlantı işleyicileri gibi belirgin çalışma modlarına sahip nesneler için idealdir.
Görev
KolayState desenini kullanarak bir ticket destek sistemi oluşturalım! Bir destek ticket'ı oluşturacak ve bu ticket'ın açılmasından, üzerinde çalışılmasına ve çözümlenmesine kadar farklı aşamalardan geçmesini sağlayacaksınız; her durum, hangi eylemlerin mümkün olduğunu ve bundan sonra ne olacağını belirleyecek.
Kodunuzu üç dosya arasında düzenleyeceksiniz:
state.go: Durum arayüzünüzü ve bir ticket'ın yaşam döngüsündeki her aşamayı temsil eden somut durumları tanımlayın.Ticket'ı işleyen ve gerekirse bir sonraki duruma geçiren
TicketStatemetoduna sahip birHandle(t *Ticket) stringarayüzü oluşturun.Üç durum uygulayın:
OpenState: işlendiğinde ticket'ıInProgressStatedurumuna geçirir veTicket opened, assigning to support teamdöndürürInProgressState: işlendiğindeResolvedStatedurumuna geçer veWorking on ticket, issue resolveddöndürürResolvedState: işlendiğinde aynı durumda kalır veTicket already resolveddöndürür
ticket.go: Mevcut durumu tutan ve davranışı bu duruma devreden ticket yapınızı oluşturun.Ticket(string) alanına ve birID(TicketState) alanına sahip birstateyapısı oluşturun. Aşağıdaki metotları ekleyin:- Ticket'ın mevcut durumunu değiştirmek için
SetState(s TicketState) - Mevcut durumun Handle metoduna devreden
Process() string
NewTicket(id string) *Ticketdurumunda başlayan bir ticket döndürenOpenStatekurucusunu oluşturun.- Ticket'ın mevcut durumunu değiştirmek için
main.go: Aynı eylemin ticket'ın mevcut durumuna bağlı olarak nasıl farklı sonuçlar ürettiğini gösterin.Bir ticket ID'si ve ticket'ın kaç kez işleneceğini okuyun. Bu ID ile yeni bir ticket oluşturun, ardından
Process()metodunu belirtilen sayıda çağırarak her sonucu ayrı bir satıra yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Ticket ID
- 2. satır: Ticket'ın işlenme sayısı
Örneğin, aşağıdaki girdi verildiğinde:
TKT-001
3Çıktınız şu şekilde olmalıdır:
Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolvedVe aşağıdaki girdi verildiğinde:
TKT-500
5Çıktınız şu şekilde olmalıdır:
Ticket opened, assigning to support team
Working on ticket, issue resolved
Ticket already resolved
Ticket already resolved
Ticket already resolvedVe aşağıdaki girdi verildiğinde:
ISSUE-42
1Çıktınız şu şekilde olmalıdır:
Ticket opened, assigning to support teamAynı ticket üzerinde Process() çağırmanın her seferinde farklı sonuçlar ürettiğine dikkat edin: Ticket durumlar arasında ilerledikçe davranışı değişir. Çözümlendikten sonra, kaç kez işlerseniz işleyin çözümlenmiş olarak kalır. Ticket nesnesi davranışını değiştiriyor gibi görünür, ancak aslında farklı durum nesnelerine devreder!
Kendin dene
package main
import (
"fmt"
)
func main() {
// Girdiyi oku
var ticketID string
var numProcesses int
fmt.Scanln(&ticketID)
fmt.Scanln(&numProcesses)
// TODO: Verilen ID ile yeni bir bilet oluştur
// TODO: Bileti belirtilen sayıda işle
// ve her sonucu ayrı bir satıra yazdır
}
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
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı11Standart Kütüphane ve OOP
io.Reader ve io.Writersort.Interface Arayüzüfmt.Stringer ArayüzüStruct'lar ile encoding/jsonhttp.Handler ArayüzüÖzet - REST API Modelleri14Tasarı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ıDekoratör olarak Middleware3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker PoolKendi başına pratik yap: Online Go derleyicisi