[안드로이드] 디자인 패턴(Design Pattern) 이란? 이전 Design Pattern 개념 정리에 이어서  행동(Behavior) 에 해당하는 커맨드 패턴(Command Pattern) 에 대해 정리하려고 합니다.         1. 커...

[안드로이드] 커맨드 패턴 (Command Pattern) 예제포함

 

[안드로이드] 디자인 패턴(Design Pattern) 이란?

이전 Design Pattern 개념 정리에 이어서

 행동(Behavior) 에 해당하는 커맨드 패턴(Command Pattern) 에 대해 정리하려고 합니다.

 

 

 

 

1. 커맨드 패턴 (Command Pattern)

"커맨드 패턴(Command pattern) 이란 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다." (위키 피디아)

 

주요 포인트는 요청사항을 객체로 캡슐화 한다는 것인데요,

캡슐화된 요청 사항은 언제든지 불러와서 활용할 수 있겠네요.




2. 커맨드 패턴 (Command Pattern) 구조

좀 더 세부적으로 알아보기 위해 아래 커맨드 패턴의 구조를 살펴보겠습니다.

 (자료출처 : 위키피디아)

  

그림만 봤을 때는 이해하기 어려운데 (저는 그랬습니다..ㅎㅎ) 최대한 쉽게 접근할 수 있는 방법을 고민을 했을 때,

아래 흐름대로 정리해주면 좋을 것 같아요.

    ① Command : 명령어 인터페이스

    ② ConcreateCommand : 명령어 인터페이스 구현

    ------------------------------- 여기까지 명령어 객체 캡슐화 준비 끝!


    ③ Client : 명령어 전달

    ④ Invoker : 명령어 저장, 명령어 실행 요청

    ⑤ Receiver : 명령어 실행

 

또는 비유적으로 생각하는 것도 정리에 도움이 됐어요.

대표적으로 식당 예를 가져오자면, "명령어" 를 "요리주문" 으로 바꾸면 얼추 맞아 떨어집니다.

    ① Command

    ② ConcreateCommand : 요리주문

    ------------------------------- 여기까지 요리주문 객체 캡슐화 준비 끝!


    ③ Client : 손님 (웨이터에게 요리주문 전달)

    ④ Invoker : 웨이터 (전달 받은 요리주문 저장, 요리사에게 요리주문 실행 요청)

    ⑤ Receiver : 요리사 (요리주문 실행)

 

 

 

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")
}
}
}
}
}

 


 

 

<참고자료>

위키피디아 - 커맨드 패턴

기계인간 John Grib

정리정리정리 - 커맨드 패턴

 

 

 

0 comments: