행위 패턴은 객체 지향 프로그래밍에서 중요한 개념 중 하나입니다. 이러한 패턴은 객체들의 상호 작용을 조직화하고, 유연하고 재사용 가능한 코드를 작성하는 데 도움을 줍니다. Python은 다양한 행위 패턴을 지원하며, 이를 활용하여 객체 간의 상호 작용을 효과적으로 구현할 수 있습니다.
1. Strategy Pattern (전략 패턴)
전략 패턴은 알고리즘을 캡슐화하고, 실행 시에 알고리즘을 선택할 수 있도록 하는 패턴입니다. 이 패턴은 같은 종류의 작업을 수행하는 다양한 알고리즘을 정의하고, 실행 시에 알고리즘을 변경할 수 있는 유연성을 제공합니다.
다음은 Strategy 패턴의 간단한 예시입니다. “전투”를 수행하는 Combat
클래스가 있고, 다양한 공격 방식을 제공하는 AttackStrategy
인터페이스와 그를 구현한 SwordAttack
와 MagicAttack
클래스가 있습니다.
class AttackStrategy:
def attack(self):
pass
class SwordAttack(AttackStrategy):
def attack(self):
print("검으로 공격합니다.")
class MagicAttack(AttackStrategy):
def attack(self):
print("마법으로 공격합니다.")
class Combat:
def __init__(self, attack_strategy):
self.attack_strategy = attack_strategy
def perform_attack(self):
self.attack_strategy.attack()
# 사용 예시
combat = Combat(SwordAttack())
combat.perform_attack() # 출력: "검으로 공격합니다."
combat = Combat(MagicAttack())
combat.perform_attack() # 출력: "마법으로 공격합니다."
2. Observer Pattern (옵저버 패턴)
옵저버 패턴은 객체들 간에 일대다 의존 관계를 정의하고, 한 객체의 상태가 변경되면 이를 의존하는 객체들에게 알림을 보내는 패턴입니다. 이 패턴은 객체 간의 느슨한 결합을 제공하므로, 한 객체의 변경이 다른 객체들에게 영향을 미치는 것을 최소화할 수 있습니다.
다음은 Observer 패턴의 간단한 예시입니다. Subject
클래스는 상태를 갖고 있으며, 상태가 변경되면 Observer
들에게 알림을 보냅니다.
class Subject:
def __init__(self):
self.observers = []
def attach(self, observer):
self.observers.append(observer)
def detach(self, observer):
self.observers.remove(observer)
def notify(self):
for observer in self.observers:
observer.update()
class Observer:
def __init__(self, name):
self.name = name
def update(self):
print(f"{self.name}이(가) 상태 변경을 감지했습니다.")
# 사용 예시
subject = Subject()
observer1 = Observer("Observer 1")
observer2 = Observer("Observer 2")
subject.attach(observer1)
subject.attach(observer2)
subject.notify() # 출력: "Observer 1이(가) 상태 변경을 감지했습니다."
# "Observer 2이(가) 상태 변경을 감지했습니다."
subject.detach(observer1)
subject.notify() # 출력: "Observer 2이(가) 상태 변경을 감지했습니다."
3. Command Pattern (커맨드 패턴)
커맨드 패턴은 작업을 객체로 캡슐화하고, 작업을 요청한 객체와 작업을 수행하는 객체를 분리하는 패턴입니다. 이 패턴은 작업을 실행, 취소, 재실행하는 등의 조작을 동적으로 관리하고자 할 때 유용합니다.
다음은 Command 패턴의 간단한 예시입니다. Command
인터페이스와 그를 구현한 LightOnCommand
와 LightOffCommand
클래스가 있습니다. Invoker
클래스는 커맨드를 실행하는 역할을 합니다.
class Command:
def execute(self):
pass
def undo(self):
pass
class Light:
def on(self):
print("조명을 켭니다.")
def off(self):
print("조명을 끕니다.")
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.on()
def undo(self):
self.light.off()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.off()
def undo(self):
self.light.on()
class Invoker:
def __init__(self):
self.commands = []
def add_command(self, command):
self.commands.append(command)
def execute_commands(self):
for command in self.commands:
command.execute()
def undo_commands(self):
for command in reversed(self.commands):
command.undo()
# 사용 예시
invoker = Invoker()
light = Light()
light_on_command = LightOnCommand(light)
light_off_command = LightOffCommand(light)
invoker.add_command(light_on_command)
invoker.add_command(light_off_command)
invoker.execute_commands() # 출력: "조명을 켭니다."
# "조명을 끕니다."
invoker.undo_commands() # 출력: "조명을 켭니다."
# "조명을 끕니다."
결론
Python은 다양한 행위 패턴을 지원하여 객체 간의 상호 작용을 구현하는 데 유용합니다. 위에서 소개한 전략, 옵저버, 커맨드 패턴은 객체 지향 개발에서 핵심적인 패턴 중 일부입니다. 이러한 패턴을 활용하여 코드의 유지 보수성, 가독성, 재사용성을 향상시킬 수 있습니다.