Komut Kalıbı
Coddy'nin Python Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 49 / 64.
Command Pattern, bir isteği bir nesne olarak kapsüller; işlemleri sıraya almanıza, istekleri günlüğe kaydetmenize ve geri alma işlevini desteklemenize olanak tanır. İşlemi çağıran nesneyi, işlemi gerçekleştiren nesneden ayırır.
İşte basit komut sınıfları:
class Command:
def execute(self):
pass
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_off()Her komut, bir alıcı nesnesindeki belirli bir işlemi kapsüller.
Asıl işi gerçekleştiren alıcıyı oluşturun:
class Light:
def turn_on(self):
print("Light is on")
def turn_off(self):
print("Light is off")Komutları çalıştıran bir çağırıcı oluşturun:
class RemoteControl:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def press_button(self):
self.command.execute()Komut desenini kullanın:
# Alıcı oluştur
light = Light()
# Komutları oluştur
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
# Çağırıcı oluştur
remote = RemoteControl()
# Farklı komutları çalıştır
remote.set_command(light_on)
remote.press_button()
remote.set_command(light_off)
remote.press_button()Geri alma işlemleri için destek ekleyin:
class UndoableCommand(Command):
def undo(self):
pass
class LightOnCommand(UndoableCommand):
def __init__(self, light):
self.light = light
def execute(self):
self.light.turn_on()
def undo(self):
self.light.turn_off()
class SmartRemote:
def __init__(self):
self.last_command = None
def execute_command(self, command):
command.execute()
self.last_command = command
def undo(self):
if self.last_command:
self.last_command.undo()
smart_remote = SmartRemote()
smart_remote.execute_command(LightOnCommand(light))
smart_remote.undo() # Işığı kapatırÇıktı:
Light is on
Light is off
Light is on
Light is offÖnemli Nokta: Command Pattern, istekleri depolanabilen, aktarılabilen ve daha sonra yürütülebilen nesnelere dönüştürür. Çağıran, işlemin nasıl gerçekleştirileceğini bilmek zorunda değildir; yalnızca komut nesnesi üzerinde execute() çağrısı yapar. Bu, geri alma/yineleme, işlemleri kuyruğa alma ve komutları günlüğe kaydetme gibi özellikleri mümkün kılar.
Görev
KolayBu meydan okumada, Komut Deseni’nin temel yapı taşı olan temel Command sınıfını command.py içinde uygulayacaksın. Bu alıştırma özellikle kapsüllemeye odaklanır: verileri özel olarak depolamak ve bir özellik aracılığıyla güvenli biçimde dışa sunmak.
Yalnızca TODO yorumlarına uygun olarak command.py dosyasını değiştir. TODO yorumları sana şunları yapman için yol gösterecek:
- Komut adını özel bir öznitelik (
_name) olarak depolamak - Bu adı salt okunur bir özellik (
name) aracılığıyla dışa sunmak - Komut adını yazdıran bir
display_info()yöntemi uygulamak
Not: Bu meydan okuma yalnızca temel Command sınıfını kapsar: Invoker, Receiver ve geri alma işlevleri sonraki derslerde tanıtılacaktır. Bu adımı tamamlamak, tam desenin üzerine inşa edildiği kapsülleme temelini sağlar.
Uygulaman driver.py tarafından test edilecek ve şunlar doğrulanacaktır:
- Temel işlevsellik ve çıktı biçimi
- Uç durumlar (boş girdiler, özel karakterler, uzun adlar)
- Salt okunur özellik koruması (
obj.name = ...atama girişimiAttributeErrorhatası vermelidir) - Özel
_nameözniteliğinin varlığı
Kendin dene
# Command sınıfını command.py dosyasından içe aktar
from command import Command
# Kapsamlı test durumu işleyicisi
test_case = input()
if test_case == "basic_test":
obj = Command("Test Name")
obj.display_info()
elif test_case == "validation_test":
obj = Command("Validation Test")
print(f"Name: {obj.name}")
elif test_case == "empty_name_test":
obj = Command("")
obj.display_info()
print(f"Empty name handled: {'Yes' if obj.name == '' else 'No'}")
elif test_case == "property_access_test":
obj = Command("Property Test")
original_name = obj.name
try:
# Bu başarısız olmalı çünkü name salt okunur bir özelliktir
obj.name = "Modified Name"
print("Property protection failed")
except AttributeError:
print("Property protected successfully")
print(f"Name unchanged: {obj.name == original_name}")
elif test_case == "multiple_commands_test":
commands = [
Command("First Command"),
Command("Second Command"),
Command("Third Command")
]
for cmd in commands:
cmd.display_info()
elif test_case == "attribute_test":
obj = Command("Attribute Test")
has_private_name = hasattr(obj, "_name")
print(f"Has _name attribute: {has_private_name}")
elif test_case == "special_chars_test":
obj = Command("!@#$%^&*()_+{}[]|\\:;\"'<>,.?/")
obj.display_info()
elif test_case == "long_name_test":
long_name = "A" * 100
obj = Command(long_name)
obj.display_info()
print(f"Name length: {len(obj.name)}")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 Nesnelerself ParametresiMetotlarÖzniteliklerYapıcı Metot (__init__)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımsuper() FonksiyonuMetot Geçersiz KılmaÇoklu KalıtımMetot Çözümleme SırasıÖzet - Çalışan Hiyerarşisi7Özel Metotlar
Sihirli Metotlara GirişOperatör Aşırı YüklemeKapsayıcı Sihirli MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım kalıplarına girişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı13Final Meydan Okumaları
E-öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi5Çok Biçimlilik (Polymorphism)
Metot Geçersiz Kılmaya Yeniden BakışDuck TypingSoyut Sınıflar ve MetotlarArayüz TasarımıÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon ve KalıtımMixinsStatik ve Sınıf MetotlarıSınıf DekoratörleriBağlam Yöneticileri11Tasarı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ıKendi başına pratik yap: Online Python derleyicisi