[DesignPattern] Strategy 패턴
개요
런타임 레벨에서 설정하거나 전환할 수 있는 교환가능한 객체를 정의
이 패턴은 위 그림에서 처럼 3가지로 구성됨
- Strategy를 사용하는 객체 : iOS에서는 주로 ViewController에서 사용되어지지만 기술적으로 교환 가능한 동작이 필요한 모든 타입의 객체일 수 있음
- Strategy Protocol : 모든 Strategy 객체가 구현해야 하는 메소드, 프로퍼티를 정의
- Strategies : Protocol을 준수하는 객체
언제 사용하는가?
교환이 가능한 두 가지 이상의 다른 행동(Behavior)이 존재할 때 사용되어짐
예를 들어 네비게이션 기능을 하는 어플리케이션을 개발한다고 생각해보자
차량을 이용한다면 차도로 안내해주는 기능이 있으면 될 것이다.
하지만 추후 자전거, 도보를 안내해야 한다면
길을 안내해야하는 전략 혹은 기능(Strategy)은 차량, 자전거, 도보 모두 동일하지만
어떤 경로로 안내해야 하는지 행동(로직 혹은 알고리즘)은 각기 다를 것이다.
개요에서의 설명과 그림을 바탕으로 구분을 지어보자
Strategy를 사용하는 객체 : Navigation 클래스
Strategy Protocol : 길을 안내하는 메소드를 정의하는 NavigationStrategy 프로토콜
Strategies : NavigationStrategy 프로토콜을 준수하는 Car, Bycle, Work 클래스
NavigationStrategy
// strategy protocol 정의
protocol NavigationStrategy: AnyObject {
// 실행할 행동
func executeLogic()
}
Car / Bycle / Work ( 교환 가능한 행동들 )
// 각 Strategy들을 선언
class WalkRoad: NavigationStrategy {
func executeLogic() {
print("도보로 안내")
}
}
class BycleRoad: NavigationStrategy {
func executeLogic() {
print("자전거 길 안내")
}
}
class CarRoad: NavigationStrategy {
func executeLogic() {
print("자동차 길 안내")
}
}
Strategy를 사용하는 Navigation
// Strategy을 사용할 객체
class Navigation {
var navigationStrategy: NavigationStrategy?
func excute() {
navigationStrategy?.executeLogic()
}
}
let navigation = Navigation()
navigation.navigationStrategy = WalkRoad()
navigation.excute()
navigation.navigationStrategy = BycleRoad()
navigation.excute()
navigation.navigationStrategy = CarRoad()
navigation.excute()
결과
도보로 안내
자전거 길 안내
자동차 길 안내
런타임 레벨에서 각 상황에 맞게 Stategy만을 교환해주었을 뿐인데
Navigation
은 excuse()
라는 하나의 인스턴스 메소드를 호출하였을 때 그 결과가 달라짐.
Navigation의 navigationStrategy는 구체적인 타입에 의존하는하는 것이 아니라 Protocol에 의존하기 때문에
보다 유연하게 사용할 수 있음
프로토콜에 의존한다는 점에서 Delegate 패턴과 유사하지만 Delegate 패턴은 런타임 레벨에서 로직의 변환이 거의 일어나지 않고 고정되어 있다는 점에 차이가 있음
정리
장점
로직(알고리즘)의 사용과 정의를 분리할 수 있음.
런타임 레벨에서 사용할 로직(알고리즘)을 변경할 수 있다.
실제 객체를 알 필요가 없이 프로토콜에 의존하기 때문에 유연하게 사용이 가능함
단점(유의 사항)
변경이 거의 없는 경우에는 오히려 코드의 복잡성이 증가함
언제 어떤 행동을 해야하는지 아는 것이 중요하다.
댓글남기기