본문 바로가기
CS/디자인패턴

디자인패턴 - 전략 패턴

by mintropy 2022. 6. 28.

 전략 패턴을 사용하지 않고, Duck이라는 슈퍼클래스를 기반으로 각 구현체는 슈퍼클래스를 상속받아서 생성한다고 하자. 그러면 구현이 단순해 보일 수 있지만, 다른 문제를 마주치게 될 것이다. 예를 들어 오리가 나는 행동을 추가하고 싶다면, Duck클래스에 그러한 행동을 추가하는 방식으로 해결할 것이다.

 여기서 큰 문제를 마주하게 된다.

특정 행동을 하거나 하지 않는 오리가 있다면,
또는 특정 행동을 다르게 하는 오리가 있다면 어떻게 해야되는가?

이는 다음과 같은 경우를 의미한다.

  • 어떤 오리가 수영하지 않는다고 하면, Duck클래스를 상속받은 후, 메서드 오버라이드 하여 특정 행동을 제한해야 하는가?
  • 오리마다 우는 방식이나 소리가 다르다고 하면, 우는 행동은 모두 재작성해야 하는가?

이 방식은 상속받는 클래스가 많아질수록, 메서드가 많아질수록 문제를 일으킬 가능성이 높다

 


 오리의 각 행동을 구현하는 인터페이스를 기반으로, 각 행동을 구현하는 방법을 적용할 수 있다.

 

 그리고 Duck 클래스에서 각 행동을 바로 구현하는 것이 아니라, 위에서 정의한 인터페이스를 기반으로 실제 날거나 우는 행위를 할 수 있는 performQuack(), performFly() 메서드를 추가한다.

 


 전략 패턴은 알고리즘 군(위의 예시에서 FlyBehavior, QuackBehavior)을 정의, 캡슐화하여 사용할 수 있도록 한다. 따라서 클라이언트로부터 알고리즘을 분리하여 독립적으로 변경할 수 있다. 이는 전략의 행위(메서드)를 더욱 다양하게 만들 수 있게 해 준다.

 


 

import abc

class Duck:
	__metaclass__ = abc.ABCMeta

	@abc.abstractmethod
	def display(self):
		pass

	def perform_fly(self):
		self.fly_behavior.fly()

	def perfrom_quack(self):
		self.quack_behavior.quack()

class FlyBehavior:
	__metaclass__ = abc.ABCMeta

	@abc.abstractmethod
	def fly(self):
		pass

class FlyWithWings(FlyBehavior):
	def fly(self):
		print("Fly with wings")

class FlyNoWay(FlyBehavior):
	def fly(self):
		print("Fly no way")

class QuackBehavior:
	__metaclass__ = abc.ABCMeta

	@abc.abstractmethod
	def quack(self):
		pass

class Quack(QuackBehavior):
	def quack(self):
		print("Quack Quack")

class MuteQuack(QuackBehavior):
	def quack(self):
		print("Mute...")


class MallardDuck(Duck):
	def __init__(self):
		self.fly_behavior = FlyNoWay()
		self.quack_behaviro = Quack()

	def display(self):
		print("Mallard Duck")

 


참조

- 헤드퍼스트 디자인패턴

댓글