CS/Design Pattern

Adapter Pattern

dawonny 2022. 3. 25. 02:28
728x90
반응형

structural design pattern : 클래스 간 구조/관계를 정의하는 패턴

 

Adapter Pattern

하나의 인터페이스를 다른 인터페이스로 전환하는 역할

-> 이러한 역할을 Adapter Pattern에도 적용

 

'이미 제공되어 있는 것'과 '필요한 것' 사이의 차이를 없애주는 디자인 패턴을 Adapter Pattern이라고 함.

 

ex) 교류 110볼트 콘센트  ~ Adapter ~ 직류 12볼트의 노트북

 

Adapter Pattern 은 Wrapper Pattern 으로 불리기도함

Wrapper 는 '감싸는 것'이라는 의미가 있는데

무엇가를 포장해서 다른 용도로 사용할 수 있게 교환해주는 것이 wrapper이며, adapter 라고 함

 

두 가지의 종류

- 클래스에 의한 Adapter Pattern(상속하는 방법)

- 인스턴스에 의한 Adapter Pattern(위임하는 방법)


Adapter Pattern : 예시

목적 : Banner 클래스를 사용해서 Print 인터페이스를 충족시키는 클래스를 만드는 것

  전원의 비유 예제 프로그램
제공되고 있는 것(adaptee) 교류 100볼트 Banner 클래스
교환 장치(adapter) 어댑터 PrintBanner 클래스
필요한 것(target) 직류 12볼트 Print 인터페이스(printWeak, printStrong)

Banner클래스 (제공되고 있는 것)

-문자열을 괄호로 묶어서 표시하는 showWithParen 메소드

- * 를 붙여 표시하는 showWithAster메소드

 

Print 클래스 (필요한 것)

-문자열을 느슨하게 표시하기 위한 printWeak 메소드

-문자열을 강하게 표시하기 위한 printStrong 메소드

 

PrintBanner 클래스 (교환 장치)

-제공되어 있는 Banner클래스를 상속해서, 필요로 하는 Print 인터페이스를 구현

- showWithParen 메소드를 사용해서 printWeak를 구현하고,

- showWithAster 메소드를 사용해서 printStrong을 구현 하고자 함

class Banner():
  def __init__(self, word):
    self.word = word
  
  def showWithParen(self):
    print("(" + self.word+")")
    
  def showWithAster(self):
    print("*"+ self.word+"*")
    
class Print():
  def printWeak(self):
    pass
  
  def printStrong(self):
    pass
  
#상속
class PrintBanner1(Banner,Print):
  def __init__(self, word):
    #현재 클래스가 어떤 클래스 인지 명확히 표기
    super(PrintBanner1, self).__init__(word)
    
  def printWeak(self):
    self.showWithParen()
    
  def printStrong(self):
    self.showWithAster()
    
#위임
class PrintBanner2(Print):
  def __init__(self, word):
    #현재 클래스가 어떤 클래스 인지 명확히 표기
    self.banner = Banner(word)

  def printWeak(self):
    self.banner.showWithParen()

  def printStrong(self):
    self.banner.showWithAster()
    
pb = PrintBanner1("hello")
pb.printStrong()
pb.printWeak()

#result : *hello*
#         (hello)

pb = PrintBanner2("hello")
pb.printStrong()
pb.printWeak()

#result : *hello*
#         (hello)

Adapter Pattern : 다른 예시

• Base class : Animal -> walk interface 가지고 있음

• Animal을 상속받은 Cat과 Dog class 모두 walk interface 가지고 있음

• makeWalk 함수는 animal을 argument로 갖고 Animal class의 walk 함수를 부를 수 있음

class Animal: #target
  def walk(self):
    pass
  
class Cat(Animal):
  def walk(self):
    print("cat walking")
    
class Dog(Animal):
  def walk(self):
    print("dog walking")
    
def makewalk(animal:Animal): #clicent
  animal.walk()
    
kitty = Cat()
bingo = Dog()

makewalk(kitty)
makewalk(bingo)
  
#result : cat walking
#         dog walking

Kitty와 bingo는 각각 Cat과 Dog object이며

makeWalk를 통해 walk함수를 실행시킬 수 있음


위와 이어지는 두번 째 예시

 

class Fish:
  def swim(self):
    print("fish swimming")
    
nemo = Fish()
makewalk(nemo)

Fish class는 swim interface만 있음

Fish class의 nemo object를 만들어서 makeWalk 함수로 넘겨주면 Error 발생

AttributeError: 'Fish' object has no attribute 'walk'

Fish class의 Object가 makeWalk interface를 사용하기 위해서는

Fish와 Animal interface를 연결시켜주는 Adapter가 있어야 함

class FishAdapter(Animal):
  def __init__(self, fish:Fish):
    self.fish = fish
    
  def walk(self):
    self.fish.swim()
    
    
nemo = Fish()
adapted_nemo = FishAdapter(nemo)

makewalk(adapted_nemo)
#result : fish swimming

그래서 FishAdapter 를 만들어줌.

FishAdapter class는 Animal을 상속받고 constructor 안에서 Fish object를 받음

 

• Nemo는 Fish Object이고 adapted_nemo는 FishAdapter에 nemo를 넘겨줌

• MakeWalk에 adapted_nemo를 넘겨주면 Fish의 Swim interface를 FIshAdapter의 walk를 통해 불러냄

 

Adapter pattern은 맞지 않는 기존의 interface를 현 재 코드에 맞게 변환시켜주는 역할을 함

 

728x90
반응형