#What
실제 업무에 적용했었던 패턴을 소개하고자 합니다
chain of responsibility 책임 연쇄 패턴 : 문제를 두 개 이상의 객체(해결 담당자)에서 해결할 기회를 주고자 할 때 사용
*'responsibility : 책임자, 담당자'의 뜻도 있다.
[개요]
- 어떤 문제나 요청사항이 발생했을 때 현재 담당자가 해결하지 못하면 다음 담당자에게 문제를 떠넘기는 패턴
- 요청은 1번째 담당자에게 우전 전달, 미해결시 2번째 담당자에게 전해진다.. 쭉쭉...
[장점]
- 문제 요청 객체와 문제 해결 객체 사이의 결합도를 낮출 수 있다
- 담당자 Chain에서 담당자를 추가/삭제/순서변경 이 자유로우며 (객체지향) 각 담당자 클래스의 코드가 간결 해진다
- 문제 해결 가능성이 높은 담당자 부터 해결 시도 하게끔 Chain을 구성 하는 것이 좋겠지요
[단점]
- 하지만 모든 담당자가 해결하지 못하는 경우도 생길 수 있으므로 문제가 해결될것이라 보장할 수 없다
- 문제 해결에 시간이 얼마나 소요될지 예측도 어렵다
- 디버깅이 어려워 질 수 있다
구체적 상황에 대해 예제로 확인해 보겠습니다
***설정***
- 한 카페에 음료 주문이 들어옵니다
- 이 카페엔 총 3명의 음료 담당자가 있고 (1)Americano 담당자 (2)Latte 담당자 (3)Ade 담당자
- 주믄 메뉴 문자열에 담당자의 'beverageType' 이 포함되어 있다면 만들 수 있다고 가정 합시다
ex) 주문 메뉴 = Ice Latte-> Latte 담당자가 만들 수 있음
주문 실행
private fun processOrder(menu: String) {
//첫번째 담당자는 AmericanoManager입니다
val firstWorker = AmericanoManager("Americano")
//그 다음 순서로는 'LatteManager -> setNextManager' 순으로 순서를 지정합니다
firstWorker.setNextManager(LatteManager("Latte")).setNextManager(AdeManager("Lemonade"))
//첫번째 담당자인 AmericanoManager에게 일을 시작하게 합니다
val orderResult = firstWorker.processMenuOrder(menu)
val result = "[메뉴 주문 결과] \n $orderResult"
}
CaffeManager.kt
abstract class CaffeManager {
//카페 주문 처리 프로세스
fun processMenuOrder(menu: String): String {
return if (makeBeverage(menu)) {
"Success To Make [$beverageType]"
} else {
nextManager?.processMenuOrder(menu)
?: "Fail To Make Beverage : No Manager To Make $menu"
}
}
//만들 수 있는 음료 종류
abstract val beverageType: String
//음료 만들기
abstract fun makeBeverage(menu: String): Boolean
//내가 처리 못하는 주문일 경우 담당할 NextManager 지정
private var nextManager: CaffeManager? = null
fun setNextManager(nextManager: CaffeManager): CaffeManager {
this.nextManager = nextManager
return nextManager
}
}
Manager.kt
class AmericanoManager(override val beverageType: String) : CaffeManager() {
override fun makeBeverage(menu: String): Boolean {
//'beverageType' 문자열을 포함한 'menu' 요청 이라면 만들 수 있는 음료라고 가정
return menu.contains(beverageType, true)
}
}
class LatteManager(override val beverageType: String) : CaffeManager() {
override fun makeBeverage(menu: String): Boolean {
//'beverageType' 문자열을 포함한 'menu' 요청 이라면 만들 수 있는 음료라고 가정
return menu.contains(beverageType, true)
}
}
class AdeManager(override val beverageType: String) : CaffeManager() {
override fun makeBeverage(menu: String): Boolean {
//'beverageType' 문자열을 포함한 'menu' 요청 이라면 만들 수 있는 음료라고 가정
return menu.contains(beverageType, true)
}
}
TEST
menu : Ice Latte
result :
[메뉴 주문 결과]
Success To Make [Latte]
-> AmericanoManager는 latte 만들기 실패
-> LatteManager가 만들어 줌
동일한 예제 GitHub에서 확인 하실 수 있습니다.
GitHub 예제 : Chain Of Responsibility : CaffeManager
문제 있을시 알려 주세요.
좋은 하루 되세요!
'Architecture, Pattern' 카테고리의 다른 글
[Android] MVVM - ViewModels AntiPatterns (0) | 2022.08.02 |
---|---|
[Pattern] MVC/MVP/MVVM (0) | 2021.10.10 |