본문 바로가기

IT/헤드퍼스트 디자인패턴

[디자인패턴] 어댑터 패턴과 퍼사드 패턴

안녕하세요 남갯입니다


오늘은 어댑터 패턴과 퍼사드 패턴에 대해 포스팅 해보려고 합니다.



어댑터 패턴



사건의 발단


객체지향 어뎁터는 그렇게 어렵지 않게 알 수 있습니다. 특히 안드로이드에서는 리사이클러뷰나 리스트뷰에 어댑터를 이용하기도 하고,

실생활에서는 유럽여행을 갈때 220v 플러그를 110v에 동작이 가능하도록 하는 어댑터를 통해 여행을 가게 됩니다.

쉽게말해서 어떤 인터페이스를 클라이언트에서의 요구하는 형태의 인터페이스로 적응시켜주는 역할을 하게 됩니다.



실제 코드를 오리와 칠면조를 통해 알아보겠습니다. 


interface Duck {
fun quack() // 꽥꽥
fun fly() // 멀리날아감
}

class MallardDuck : Duck {
override fun quack() {
println("quack")
}

override fun fly() {
println("I'm fiying")
}
}

interface Turkey {
fun gobble() // 골골
fun fly() // 조금 날아감
}

class WildTurkey : Turkey {
override fun gobble() {
println("Gobble gobble")
}

override fun fly() {
println("I'm flying a short distance")
}
}


위와같이 오리와 칠면조형태의 코드를 만듭니다.


그후


class TurkeyAdapter(val turkey: Turkey) : Duck {
override fun quack() {
turkey.gobble()
}

override fun fly() {
for (i in 0..4)
turkey.fly()
}
}


칠면조 adapter를 통해 오리에 적응을 시키도록 만듭니다.



fun main(){
var mallardDuck = MallardDuck()
var wildTurkey = WildTurkey()
var turkeyAdapter : Duck = TurkeyAdapter(wildTurkey)
// turkey우는거는
wildTurkey.gobble()
wildTurkey.fly()
//duck 우는거는
testDuck(mallardDuck)
// turkeyAdapter의 우는거는
testDuck(turkeyAdapter)
}
fun testDuck(duck : Duck){
duck.quack()
duck.fly()
}

이렇게 하게되면 칠면조가 우는것과 오리가우는것

오리로 위장한 turkeyAdapter가 우는것을 볼 수 있습니다.


이렇게 보시다시피 어댑터패턴은 한 인터페이스를 다른 인터페이스로 변환하는 용도로 사용되게 됩니다.


어댑터 패턴의 정의

어댑터 패턴이란 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환합니다.

어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸수 없는 클래스를 연결해서 쓸 수 있습니다.




패턴 용도 연결하기!

a 데코레이터

b 어댑터

c 퍼사드

-----

1 한 인터페이스를 다른 인터페이스로 변환

2 인터페이스는 바꾸지 않고 책임 기능만 추가

3 인터페이스를 간단하게 바꿈







정답 : a = 2 , b = 1 , c = 3



퍼사드패턴





사건의 발단


홈시어터를 구축하려고 합니다. DVD, 프로젝터 , 스크린, 음향기계 , 팝콘기계가 있는 시스템을 구축하게 되었습니다.

하지만 영화를 보기위한 과정들이 너무나 복잡합니다.

팝콘기계를 켜고, 튀기고 전등 조절, 스크린 내리고, 프로젝터.......등등

영화를 다 시청하게되면 위와같은동작은 역순으로 또 처리를 해야 합니다.

퍼사드패턴을 이용하게되면 이런 복잡한 일들을 간단하게 처리하고 영화를 즐길 수 있습니다.



class Amplifier{
}

class Tuner{
}
class DvdPlayer{
}
class CdPlayer{
}
class Projector{
fun on() = println("projecter on")
fun off() = println("projecter on")
}
class TheaterLights{
fun dim(value: Int) = println("light dim $value")
}
class Screen{
fun up() = println("screen up")
fun down() = println("screen down")
}
class PopcornPopper{
fun on()= println("popcorn on")
fun off()= println("popcorn off")
}


class HomeTheatherFacade(val amplifier: Amplifier,
val tuner: Tuner,
val dvdPlayer: DvdPlayer,
val cdPlayer: CdPlayer,
val projector: Projector,
val theaterLights: TheaterLights,
val screen: Screen,
val popcornPopper: PopcornPopper
){
fun watchMovie(){
popcornPopper.on()
projector.on()
screen.down()
theaterLights.dim(10)
}
fun endMovie{
popcornPopper.off()
projector.off()
screen.up()
theaterLights.dim(0)
}
}


일단 홈시어터를 이용한 facade 퍼사드를 만든후에 watchMovie와 endMovie에 사용할것과 종료할것을 넣어줍니다.


이렇게 하게 된다면 HoemTheaterFacade를 만들어 watch와 end를 부르게 되면 손 쉽게 영화를 볼 수 있습니다.



퍼사드 패턴의 정의


어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공합니다. 퍼사드에서 고수준 인터페이스를 정의하기 때문에

서브시스템을 더 쉽게 사용할 수 있습니다.