티스토리 뷰
반응형
Head First - Design Patterns 의 템플릿 메소드 패턴 기반으로 작성하였습니다. 자세한 설명은 도서를 참고해주세요.
이번 포스트는 브릿지패턴에 대해서 이야기하려고 합니다.
브리지 사전전 정의는 기본적으로 다리 구조물을 뜻합니다. 다리의 역할은 강이나 두 지점을 건널 수 있게 만드는 시설을 의미하는데요. 왜 이름을 브리지 패턴으로 선언하고 브리지 패턴의 장점과 단점을 알아보겠습니다.
브리지 패턴을 왜 사용하는가?
브리지 패턴은 구조(Structural)패턴으로써 클래스 및 객체들읠 구성을 통하여 구현 뿐만 아니라 추상화된 부분까지 변경시켜야하는 경우에는 브리지 패턴을 사용하면됩니다.
예를들어서 만능 리모컨을 만든다고 가정합시다. 조금 더 편한 가정을 위해서 모든 TV의 리모콘은 똑같은 추상화된 부분으로 작업을 한다고 가정합니다.
리모컨 컨트롤의 추상클래스와 TV 라는 인터페이스를 서로 다른 클래스 계층구조에 집어 넣음으로써 각각 독립적으로 추가 요구사항에 변경할 수 있습니다.
- Abstraction (RemoteControl)
: 추상화된 인터페이스를 정의합니다. Implementor 객체에 대한 참조 유지 관리합니다. - RefinedAbstraction (ConcrereRemote)
: 추상화에 의해 정의된 인터페이스를 확장합니다. - Implementor(TV)
: 구현 클래스의 인터페이스를 정의합니다. 이 인터페이스는 Abstraction의 인터페이스와 일치 할 필요는 없습니다. - ConcreteImplementor (RCA, Sony)
: Implementor의 인터페이스를 구현하고 구체적인 구현을 정의합니다.
소스코드를 통한 브리지 패턴 알아보기
UMl 로 알아본 브리지 패턴에 대해서 코드로 알아봅시다.
/**
* 추상화된 인터페이스
* Abstraction
*/
abstract class RemoteControl(var tvFactory: TvFactory?) {
var tv: TV? = null
open fun on(){
tv?.on()
}
open fun off(){
tv?.off()
}
// 구상 서브 클래스는 구현 클래스 계층구조 쪽의 메서드가 아닌 추상 클래스 쪽의 메소드를 통해서 구현
open fun setChannel(channel: Int?){
tv?.tuneChannel(channel)
}
open fun getChannel(): Int?{
return tv?.getChannel()
}
open fun setTV(type: String?){
try {
tv = tvFactory?.getTV(type)
}catch (e: Exception){
e.printStackTrace()
}
}
}
/**
* RefinedAbstraction
*/
class GenericRemote(tvFactory: TvFactory?) : RemoteControl(tvFactory) {
fun nextChannel() {
getChannel()?.let{channel->
setChannel(channel + 1)
}
}
fun prevChannel() {
getChannel()?.let{channel->
setChannel(channel - 1)
}
}
}
/**
* implementor
*/
interface TV {
fun on()
fun off()
fun tuneChannel(channel: Int?)
fun getChannel(): Int?
}
/**
* ConcreteImplementor
*/
class RCA: TV {
companion object {
private const val DEFAULT_CANNEL = 1
}
var channel = DEFAULT_CANNEL
override fun on() {
Log.d(MainApplication.TAG, "Turning on the RCA TV")
}
override fun off() {
Log.d(MainApplication.TAG, "Turning off the RCA TV")
}
override fun tuneChannel(channel: Int?) {
this.channel = channel ?: DEFAULT_CANNEL
Log.d(MainApplication.TAG, "Set the RCA TV Channel to ${this.channel}")
}
override fun getChannel(): Int? {
return channel
}
}
class TvFactory {
// RCA 외에 SONY, SAMSUNG 등 TV 타입을 다양하게 설정할 수 있다.
companion object {
const val RCA = "RCA"
}
@Throws(Exception::class)
fun getTV(type: String?): TV{
return when(type){
RCA -> RCA()
else -> throw Exception("Invalid TV Type")
}
}
}
브리지 패턴의 장점과 단점은?
장점
- 구현을 인터페이스에 완전히 결합시키지 않았기 때문에 구현과 추상화된 부분을 구분할 수 있습니다.
- RemoteControl 과 TV 계층의 분리
- 추상화된 부분과 구현 부분을 독립적으로 확장 할 수 있습니다. 만약 추상화된 부분을 구현한 구상 클래스를 바꿔도 클라이언트 쪽에는 영향을 끼치지 않게됩니다.
단점
- 인터페이스와 실제 구현부를 다른 방식으로 구현하기에 디자인이 복잡해질 수 있습니다.
마무리
브리지 패턴에 대해서 알아봤습니다.
구현 뿐만 아니라 추상화된 부분까지 변경이 필요할 때 브리지 패턴을 활용해서 독립적으로 확장하는 것에서 고민해도 좋을거 같습니다.
출처
[도서] Head First - Design Patterns
반응형
'프로그래밍 > Design Patterns' 카테고리의 다른 글
역할 사슬(Chain of Responsibility) 패턴 (0) | 2022.01.21 |
---|---|
빌더(Builder) 패턴 (0) | 2022.01.20 |
템플릿 메소드 패턴 (0) | 2021.09.27 |
데코레이터 패턴(Decorator Pattern) (0) | 2021.08.09 |
싱글톤 패턴 (Singleton Pattern) (0) | 2017.12.27 |
댓글
최근에 올라온 글
최근에 달린 댓글
TAG
- 고시문헬퍼
- RXjava
- push
- 점수판
- 탁구
- Android Studio
- 스코어헬퍼
- view
- 패턴
- IT
- 코틀린
- MCC
- IOS
- missioon
- issue
- Kotlin
- Android
- swift
- 미션차이나센터
- 고시문
- 디자인패턴
- DI
- 알고리즘
- 선교
- 임용고시
- flutter
- 안드로이드
- missionchina
- java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함