전략 패턴이라고도 불리는 Strategy Pattern은 객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여, 객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법을 말합니다.
전략 : 어떤 목적을 달성하기 위해 일을 수행하는 방식, 비즈니스규칙, 문제를 해결하는 알고리즘입니다.
다음 그림이미지와 같이 중간에 Interface를 사용하여 직접적인 의존성을 주지않고 런타임시 주입이되는 형식으로 구현됩니다.
전략 패턴 예시를 보여드리겠습니다.
val message = "Hello"
println("$message : Written from Android")
결과는 다음과 같이 선언됩니다.
"Hello: Written from Android"가 출력됩니다.
이를 사용자 마음대로 변환을하려면 MessageConverter을 만들어야합니다.
Class MessageConverter(Private var messageGenerateStrategy : MessageGenerateStrategy) {
fun convert(string : String) : String {
return messageGenerateStrategy.process(string)
}
fun setStrategy(messageGenerateStrategy : MessageGenerateStrategy) {
this.messageGenerateStrategy = messageGenerateStrategy
}
}
MessageConverter은 MessageGenerateStrategy(메세지 생성 전략) 객체로 인자로 받으며 convert 함수를 수행 시 MessageGenerateStrategy의 전략에 따라 다르게 코드를 만들어 냅니다. 또한 setStrategy 함수를 통해 MessageGenerateStrategy를 동적으로 바꿀 수도 있습니다.
Kotlin은 추상 클래스로서 사용되는 sealed class를 제공하기 때문에 sealed class를 사용해 MessageGenerateStrategy를 process라는 abstract fun이포함된 형태로 만들어줍니다.
sealed class MessageGenerateStrategy {
abstract fun process(string : String) : String
}
이제 이를 상속받는 클래스를 만들어보겠습니다.
AttachHeader입니다. 메세지의 앞부분에 문자를 붙일 수 있는 전략입니다.
data class AttachHeader(val header : String) : MessageGenerateStrategy() {
override fun process(string : String) : String {
return "$header $string"
}
}
두 번째는 대문자로 전환해주는 전략입니다.
object UpperCase : MessageGenerateStrategy() {
override fun process(string : String) : String {
return string.uppercase()
}
}
이렇게 생성한 전략들을 사용해보겠습니다.
val message = "Hello"
val fromAndroidStrategy = MessageGenerateStrategy.AttachHeader("Message : "
messageConverter.setStrategy(messageHeaderStrategy)
println(messageConverter.convert(message))
결과는 다음과 같습니다.
"Message : Hello"
messageConverter.setStrategy(MessageGenerateStrategy.UpperCase)
println(messageConverter.convert(message))
결과는 다음과 같습니다.
"HELLO"
전략 패턴은 유연하게 코드를 수정하기 위해 사용되는 디자인 패턴입니다. Kotlin에서는 다양한 전략을 seal 할 수 있는 sealed class를 제공하므로 sealed class를 사용하는 것을 권장합니다.