[안드로이드] 디자인 패턴(Design Pattern) 이란?
이전 Design Pattern 개념 정리에 이어서
행동(Behavior) 에 해당하는 커맨드 패턴(Command Pattern) 에 대해 정리하려고 합니다.
1. 커맨드 패턴 (Command Pattern)
"커맨드 패턴(Command pattern) 이란 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다." (위키 피디아)
주요 포인트는 요청사항을 객체로 캡슐화 한다는 것인데요,
캡슐화된 요청 사항은 언제든지 불러와서 활용할 수 있겠네요.
2. 커맨드 패턴 (Command Pattern) 구조
좀 더 세부적으로 알아보기 위해 아래 커맨드 패턴의 구조를 살펴보겠습니다.
(자료출처 : 위키피디아)
그림만 봤을 때는 이해하기 어려운데 (저는 그랬습니다..ㅎㅎ) 최대한 쉽게 접근할 수 있는 방법을 고민을 했을 때,
아래 흐름대로 정리해주면 좋을 것 같아요.
① Command : 명령어 인터페이스
② ConcreateCommand : 명령어 인터페이스 구현
------------------------------- 여기까지 명령어 객체 캡슐화 준비 끝!
③ Client : 명령어 전달
④ Invoker : 명령어 저장, 명령어 실행 요청
⑤ Receiver : 명령어 실행
또는 비유적으로 생각하는 것도 정리에 도움이 됐어요.
대표적으로 식당 예를 가져오자면, "명령어" 를 "요리주문" 으로 바꾸면 얼추 맞아 떨어집니다.
① Command
② ConcreateCommand : 요리주문
------------------------------- 여기까지 요리주문 객체 캡슐화 준비 끝!
③ Client : 손님 (웨이터에게 요리주문 전달)
④ Invoker : 웨이터 (전달 받은 요리주문 저장, 요리사에게 요리주문 실행 요청)
3. 커맨드 패턴 (Command Pattern) 예제
위에서 예를 들었던 식당에 대해 커맨드 패턴을 적용한 예제 입니다. ("계산"에 대한 명령어도 추가되었습니다.)
① Command : 명령어 인터페이스
interface Command {
fun execute()
}
② ConcreateCommand : 명령어 인터페이스 구현
class ConcreteCommand {
class OrderCommand(private val chef: Receiver.Chef): Command {
override fun execute() {
chef.cook()
}
}
class PayCommand(private val cashier: Receiver.Cashier): Command {
override fun execute() {
cashier.counting()
}
}
}
③ Client : 명령어 전달
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val invoker = Invoker()
println("First client")
invoker.addToQueue(
// 명령어 전달
ConcreteCommand.OrderCommand(Receiver.Chef(Menu.STEAK)),
ConcreteCommand.OrderCommand(Receiver.Chef(Menu.PASTA)),
ConcreteCommand.OrderCommand(Receiver.Chef(Menu.DESSERT)),
ConcreteCommand.PayCommand(Receiver.Cashier(PayMethod.CARD))
).processCommands() // 명령어 실행 요청
println("Second client")
invoker.addToQueue(
// 명령어 전달
ConcreteCommand.OrderCommand(Receiver.Chef(Menu.STEAK)),
ConcreteCommand.OrderCommand(Receiver.Chef(Menu.PASTA)),
ConcreteCommand.PayCommand(Receiver.Cashier(PayMethod.CASH))
).processCommands() // 명령어 실행 요청
}
}
④ Invoker : 명령어 저장, 명령어 실행 요청
class Invoker {
private val queue = ArrayList<Command>()
fun addToQueue(vararg orderCommands: Command): Invoker {
// 명령어 저장
return apply {
queue.addAll(orderCommands)
}
}
fun processCommands(): Invoker {
// 명령어 실행 요청
return apply {
queue.forEach { it.execute() }
queue.clear()
}
}
}
⑤ Receiver : 명령어 실행
class Receiver {
enum class Menu { STEAK, PASTA, DESSERT }
enum class PayMethod { CARD, CASH }
class Chef(private val menu: Menu) {
fun cook() { // 명령어 실행 (by execute)
when (menu) {
Menu.STEAK -> {
println("Cook Steak")
}
Menu.PASTA -> {
println("Cook Pasta")
}
Menu.DESSERT -> {
println("Cook Dessert")
}
}
}
}
class Cashier(private val payMethod: PayMethod) {
fun counting() { // 명령어 실행 (by execute)
when (payMethod) {
PayMethod.CARD -> {
println("Counting Card")
}
PayMethod.CASH -> {
println("Counting Cash")
}
}
}
}
}
<참고자료>
0 comments: