Menu
Coddy logo textTech

Durum Kalıbı

Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 53 / 64.

State Pattern (Durum Deseni), bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanır. Nesne, mevcut durumuna bağlı olarak sınıfını değiştiriyormuş gibi görünür.

Bir trafik lambası için basit durum sınıfları şunlardır:

class RedState:
    def next_state(self, light):
        print("Red -> Green")
        light.state = GreenState()
    
    def current_color(self):
        return "Red"

class GreenState:
    def next_state(self, light):
        print("Green -> Yellow")
        light.state = YellowState()
    
    def current_color(self):
        return "Green"

class YellowState:
    def next_state(self, light):
        print("Yellow -> Red")
        light.state = RedState()
    
    def current_color(self):
        return "Yellow"

Her durum, bir sonraki duruma geçerken ne olacağını tanımlar.

Mevcut durumu tutan bir bağlam (context) sınıfı oluşturun:

class TrafficLight:
    def __init__(self):
        self.state = RedState()  # Kırmızı ile başla
    
    def change(self):
        self.state.next_state(self)
    
    def get_color(self):
        return self.state.current_color()

Trafik lambası, davranışı mevcut durum nesnesine devreder.

Trafik ışığını kullanın:

light = TrafficLight()
print(f"Current: {light.get_color()}")

light.change()  # Kırmızı -> Yeşil
print(f"Current: {light.get_color()}")

light.change()  # Yeşil -> Sarı
print(f"Current: {light.get_color()}")

light.change()  # Sarı -> Kırmızı
print(f"Current: {light.get_color()}")

Basit bir oynatıcı ile başka bir örnek oluşturun:

class PlayingState:
    def play(self, player):
        print("Already playing")
    
    def stop(self, player):
        print("Stopping music")
        player.state = StoppedState()

class StoppedState:
    def play(self, player):
        print("Starting music")
        player.state = PlayingState()
    
    def stop(self, player):
        print("Already stopped")

class MusicPlayer:
    def __init__(self):
        self.state = StoppedState()
    
    def play(self):
        self.state.play(self)
    
    def stop(self):
        self.state.stop(self)

player = MusicPlayer()
player.play()   # Müzik başlatılıyor
player.play()   # Zaten çalıyor
player.stop()   # Müzik durduruluyor
player.stop()   # Zaten durduruldu

Çıktı:

Current: Red
Red -> Green
Current: Green
Green -> Yellow
Current: Yellow
Yellow -> Red
Current: Red
Starting music
Already playing
Stopping music
Already stopped

Anahtar Nokta: State Pattern, duruma özgü davranışı ayrı sınıflarda kapsüller ve bağlam (context) nesnesinin mevcut duruma delege etmesini sağlar. Durum değiştiğinde, davranış otomatik olarak değişir. Bu, karmaşık if/else ifadelerini ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır.

challenge icon

Görev

Kolay

Bu meydan okumada, state.py dosyasındaki State sınıfını uygun kapsülleme ve metotlarla gerçekleştireceksiniz. Dosya, uygulamanıza adım adım rehberlik etmek için detaylı TODO yorumları içerir.

Test paketi, uygulamanızın tüm gereksinimleri karşıladığını ve istisnai durumları doğru şekilde ele aldığını doğrulamak için tasarlanmıştır. Beklenen davranışı anlamak ve çözümünüzü geliştirmek için test sonuçlarını kullanın.

Kopya kağıdı

Durum Deseni (State Pattern), bir nesnenin iç durumu değiştiğinde davranışını değiştirmesine olanak tanır. Nesne, mevcut durumuna bağlı olarak sınıfını değiştiriyormuş gibi görünür.

Her bir durum için davranışı tanımlayan durum sınıfları oluşturun:

class RedState:
    def next_state(self, light):
        print("Red -> Green")
        light.state = GreenState()
    
    def current_color(self):
        return "Red"

class GreenState:
    def next_state(self, light):
        print("Green -> Yellow")
        light.state = YellowState()
    
    def current_color(self):
        return "Green"

Mevcut durumu tutan bir bağlam (context) sınıfı oluşturun:

class TrafficLight:
    def __init__(self):
        self.state = RedState()  # Kırmızı ile başla
    
    def change(self):
        self.state.next_state(self)
    
    def get_color(self):
        return self.state.current_color()

Kullanım örneği:

light = TrafficLight()
print(f"Current: {light.get_color()}")  # Mevcut: Red
light.change()  # Red -> Green
print(f"Current: {light.get_color()}")  # Mevcut: Green

Durum Deseni, duruma özgü davranışı ayrı sınıflarda kapsüller ve bağlam nesnesinin mevcut duruma delege etmesini sağlar. Bu, karmaşık if/else ifadelerini ortadan kaldırır ve yeni durumlar eklemeyi kolaylaştırır.

Kendin dene

from state import State

# Kapsamlı test senaryosu işleyicisi
test_case = input()

if test_case == "basic_test":
    obj = State("Test Name")
    obj.display_info()

elif test_case == "validation_test":
    obj = State("Validation Test")
    print(f"Name: {obj.name}")

elif test_case == "empty_name_test":
    obj = State("")
    obj.display_info()
    print(f"Name property: {obj.name}")

elif test_case == "special_chars_test":
    obj = State("Test@#$%")
    obj.display_info()
    print(f"Name property: {obj.name}")

elif test_case == "long_name_test":
    long_name = "A" * 100
    obj = State(long_name)
    obj.display_info()
    print(f"Name length: {len(obj.name)}")

elif test_case == "multiple_states_test":
    states = [
        State("California"),
        State("Texas"),
        State("New York"),
        State("Florida")
    ]
    
    for state in states:
        state.display_info()
        print(f"Name via property: {state.name}")

elif test_case == "attribute_access_test":
    obj = State("Access Test")
    # Özel özniteliğe doğrudan erişim (önerilmez)
    print(f"Direct access (not recommended): {obj._name}")
    # Özellik (property) üzerinden erişim (önerilir)
    print(f"Property access (recommended): {obj.name}")

elif test_case == "property_behavior_test":
    obj = State("Original Name")
    print(f"Original name: {obj.name}")
    
    # İsmi değiştirmeyi dene (ayarlayıcı -setter- olmadığı için başarısız olacaktır)
    try:
        obj.name = "New Name"
    except AttributeError as e:
        print(f"Error when trying to modify name: {e}")
    
    # İsmin değişmediğini göster
    print(f"Name after modification attempt: {obj.name}")
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler