Skip to content

Command Pattern

Command pattern’in temel amacı, nesnelerin arasındaki ilişki ve etkileşimleri düzenlemektedir, temelde bir istemcinin isteğini bir nesneye bağlar, bunu yapaykende isteğin hangi nesne tarafından ve nasıl işleneceği tamamen soyutlanmış durumdadır. Sonuçta elde ettiğimiz yapıda işlem istemciden gelen bir isteğe göre nesnelere bağımlı olarak gerçekleştirilecek, nesneler arasındaki bağımlılık en aza inerken, işlem daha esnek, modüler ve yeniden kullanılabilir hale gelecektir. Genel anlamda nesnelerin birbirleriyle iletişim kurarak işemler gerçekleştirmesi gereken durumlar için efektif bir çözüm olarak uygulanabilir.

Örnek bir senaryoyu ele alalım: Bir metin düzenleme uygulaması geliştirdiğinizi düşünün, kullanıcının bir butona tıklaması sonucu bir belgeyi kaydetmesi gerektiğinde, kaydetme işlemi, butona bağlı bir olay işleyici tarafından doğrudan gerçekleştirilir. Ancak, belgenin kaydedilmesi gerektiği durumlarda, farklı yerlerdeki farklı bileşenler tarafından da bu işlem tetiklenebilir. Bu durumda, kaydetme işlemi, kodun birçok yerinde tekrarlanacak ve bakımı zor hale gelecektir.

Command tasarım deseni, bu sorunu çözmek için kullanılabilir. Belgenin kaydedilmesi gerektiğinde, bir Command nesnesi oluşturulur ve bu nesne, kaydetme işlemini gerçekleştiren bir sınıfa gönderilir. Bu sayede, kaydetme işlemi, birçok farklı yerde Command nesnesi üzerinden tetiklenebilecektir.

https://www.dofactory.com/img/diagrams/net/command.png

UML diagramını inceleyecek olursak;

Command: komutların uygulanması için gereken yöntemleri tanımlayan bir arayüz veya sınıf olabilir, uygulanacak işlemin adını, parametreleri ve işlemin geri alınması için gereken bilgileri içerir.

ConcreteCommand: Command arayüzünü uygulayan sınıftır ve bir işlemi gerçekleştirmek için gerekli tüm yöntemleri ve bilgileri içerir.

Invoker: Command nesnelerinin yönetildiği bir sınıftır. Command nesnelerini alır ve bir command nesnesinin uygulanmasını talep eder.

Receiver: Bir işlemi gerçekleştirmek için kullanılan nesnedir. ConcreteCommand nesneleri, Receiver nesnesini kullanarak işlemleri gerçekleştirir.

Örnek kod üzerinden ilerlemek için şöyle bir senaryomuz olsun: Akıllı ev aletleri için uygulama geliştirdiğinizi düşünün akıllı bir ampulün uzaktan mobil cihaz üzerinden açılma, kapanma ve renk değiştirme işlemlerini yazıyor olalım.

from abc import ABC, abstractmethod


# Command abstract class
class Command(ABC):
    @abstractmethod
    def execute(self):
        pass


# Concrete Command classes
class TurnOnCommand(Command):
    def __init__(self, device):
        self.device = device
    
    def execute(self):
        self.device.turn_on()


class TurnOffCommand(Command):
    def __init__(self, device):
        self.device = device
    
    def execute(self):
        self.device.turn_off()
    
        
class ChangeColorCommand(Command):
    def __init__(self, device, color_code):
        self.device = device
        self.color_code = color_code
        
    def execute(self):
        self.device.change_color(self.color_code)


# Receiver class
class Light:
    def turn_on(self):
        print("Light is on")
    
    def turn_off(self):
        print("Light is off")
        
    def change_color(self, color_code):
        print(f"Light color is : {color_code}")


# Invoker class
class RemoteControl:
    def __init__(self):
        self.command = None
    
    def set_command(self, command):
        self.command = command
    
    def press_button(self):
        self.command.execute()


# Client code
if __name__ == "__main__":
    # Create receiver object
    light = Light()
    
    # Create concrete command objects
    turn_on = TurnOnCommand(light)
    turn_off = TurnOffCommand(light)
    change_color_white = ChangeColorCommand(light, 'white')
    change_color_red = ChangeColorCommand(light, 'red')
    
    
    # Create invoker object
    remote = RemoteControl()
    
    # Set command for invoker
    remote.set_command(turn_on)
    
    # Press button to execute command
    remote.press_button()
    
    remote.set_command(turn_off)
    remote.press_button() 
    
    remote.set_command(change_color_white)
    remote.press_button()
    remote.set_command(change_color_red)
    remote.press_button()

-----------------------------------------------------------------------
Output: 
Light is on
Light is off
Light color is : white
Light color is : red

Sonuç olarak açılma, kapanma ve renk değiştirme komutlarını yaratıp, RemoteAccess classı üzerinden Light objesinin farklı methodlarını çalıştırmış olduk.

Command pattern pratikte birçok durumda kullanışlı ve etkili bir desendir ve uygun bir şekilde uygulandığında, kodu daha düzenli, modüler ve anlaşılır hale getirebilir ancak doğru bir mimari seçim olmadığı durumlarda, kodun karmaşıklığı ve bakım maliyeti doğrudan artacaktır.


Sources:

Published inBehavioral Design PatternsDesign Patterns

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *