취업과 기본기 튼튼/빽 투더 기본기
[디자인 패턴 10편] 행동 패턴, 스트레티지(Strategy)
흠시
2020. 3. 21. 14:44
1. 개념
스트레티지 패턴은 행동/전략 등 동일계열의 알고리즘들을 인터페이스-캡슐화하고,
알고리즘들을 컴포지션(위임 형태로) 가지는 패턴이다.
1.1. 구조
- Context
- 클라이언트가 직접 사용하는 클래스
- Strategy 인터페이스를 위임하고(has) 하고 있음.
- Strategy
- 구체적인 알고리즘들의 공통 스펙을 정의하는 클래스
- ConcreteStrategy
- 구체적인 알고리즘들을 구현하는 클래스
1.2. 장점
- 상황에 따라 사용할 알고리즘을 쉽게 바꿀 수 있다.
- 알고리즘 구현부와 사용부가 분리되어 있다.
- 인터페이스로 사용자는 일관성있게 알고리즘을 가져다 쓸 수 있고,
- 각 알고리즘들은 동일한 인터페이스를 가지되, 각각 목적에 따라 구현은 다르게할 수 있다.
1.3. 단점
- 다 사용하지 않는 정보들을 모든 알고리즘이 떠안아야 한다.
- 각 구체적인 알고리즘들마다 필요한 입력 파라미터가 다 다를 수 있다.
- 하지만 인터페이스로 파라미터가 고정되어 있으므로, 굳이 이 알고리즘에 필요없는 파라미터도 다 받게된다.
- 알고리즘 수 만큼 전체 객체 수가 증가한다.
1.4. 활용 상황
- 상황에 따라 사용해야할 알고리즘(전략)을 클라이언트가 정해야 할 때.
- 동일 계열의 알고리즘들을 인터페이스로 통일하여 제공해야 할 때.
2. 구현
클라이언트는 Context
객체를 사용한다고 가정하자.Context
내 필요한 알고리즘들을 다음과 같이 사용할 수 있다.
if __name__ == "__main__":
context = Context(ConcreteStrategyA())
context.do_some_business_logic()
context = Context(ConcreteStrategyB())
context.do_some_business_logic()
Context
는 다음과 같이 정의되어 있음.
class Context():
def __init__(self, strategy: Strategy) -> None:
self._strategy = strategy
def do_some_business_logic(self) -> None:
result = self._strategy.do_algorithm(["a", "b", "c", "d", "e"])
동일계열 알고리즘들의 인터페이스 정의
class Strategy(ABC):
@abstractmethod
def do_algorithm(self, data: List):
pass
위 인터페이스를 따르는 각 알고리즘 구현체 정의
class ConcreteStrategyA(Strategy):
def do_algorithm(self, data: List) -> List:
return sorted(data)
class ConcreteStrategyB(Strategy):
def do_algorithm(self, data: List) -> List:
return reversed(sorted(data))