# 설명
어댑터 패턴의 주요 개념은 요약하면 아래와 같다.
서로 다른 인터페이스를 중간에서 연결해주어 규격을 맞추어주는 것.
즉, 인터페이스가 서로 다른 것을 어댑터로 하여금 중간 매개체로 연결을 시켜주는 것이다. 안드로이드를 공부하다보면 리사이클러뷰를 구성할때 어댑터를 사용해야 했다. 영문도 모르고 사용했지만, 거기서 어댑터는 View와 데이터 사이를 중간 어댑터에서 관리를 도맡아 주는 역할을 했다.
어댑터 패턴을 사용하면 이미 사용중이거나 정의된 인터페이스들을 중간(어댑터)에서 매개체의 역할로써 사용하여, 이미 사용중인 클래스를 수정하지 않고 사용하게 해준다. 디자인패턴의 5가지 원칙 OCP원칙을 충족시킨다. Warrior 예제를 보면 어떤것인지 알 수 있을 것이다.
어댑터를 이용하는 방법은 크게 두가지가 있다. 상속과 합성을 이용하는 방법이다. 합성을 이용하면 조금더 유연하게 다룰 수 있다.
- 상속 방법
- 합성방법 (has)
다이어그램을 간단히 설명해보자면, Client는 Target이라는 인터페이스를 사용한다. 그러나 우리가 구현한(된) Adaptee객체는 Client가 원하는 인터페이스 방법을 사용하지 않는다. 이를 Adapter를 사용하여 Adaptee가 Target에 맞는 인터페이스를 사용할 수 있도록 도와준다. 220V를 사용하는 우리나라 충전콘센트는 외국(110V)에서는 그 규격이 맞지않는 경우가 있다. 우린 이때 돼지코멀티어댑터를 사용하여 규격을 맞추는 경우가 있는데, 어댑터 패턴도 이와 같은 개념이다.
Adapter는 Client가 요구하는 인터페이스 규격인 Target을 상속(인터페이스or추상클래스)받는다. 이로써 Adapter에는 Target이라는 규격이 생겼고, Adaptee를 합성or상속의 방법을 사용해서 Adapter에 생긴 새로운 규격에 구현 할 수 있도록 한다.
# 예제 및 코드 - Print Banner
- Client는 Print라는 인터페이스를 사용해야 한다.
- 이미 구현된 Banner는 이와 맞는 규격이 아니다.
- Adapter를 만들어 배너를 Client에 맞는 규격으로 사용 할 수 있도록 한다.
- 상속과 합성의 방법으로 구현해본다.
public interface Print {
public void printWeak();
public void printStrong();
}
## Banner
public class Banner {
public String str;
Banner(String str){
this.str = str;
}
public void showWithParen(){
System.out.println("(" + str + ")");
}
public void showWithAster(){
System.out.println("*" + str + "*");
}
}
## Adapter - 합성방법 사용
public class AdapterWithImplements implements Print{
Banner banner;
AdapterWithImplements(String str){
banner = new Banner(str);
}
@Override
public void printWeak() {
banner.showWithParen();
}
@Override
public void printStrong() {
banner.showWithAster();
}
}
## Adapter - 상속방법 사용
public class AdapterWithExtends extends Banner implements Print{
AdapterWithExtends(String str) {
super(str);
}
@Override
public void printWeak() {
showWithParen();
}
@Override
public void printStrong() {
showWithAster();
}
}
## Test
public class Test {
public static void main(String[] args) {
Print p = new AdapterWithImplements("HELLO, Implements!");
p.printStrong();
p.printWeak();
System.out.println(" ====== ");
Print p2 = new AdapterWithExtends("Hello, Extends!");
p2.printStrong();
p2.printWeak();
}
}
# 예제 - Warrior
- Client는 Fighter라는 인터페이스로 공격, 방어, 귀환을 정의했다.
- Warrior는 Fighter라는 인터페이스를 상속받아 구현했기 때문에 인터페이스를 만족한다.
- Wizard는 아주 옛날부터 있던 직업이였기 때문에, 많은 유저들이 사용중이고 Client가 요구하는 인터페이스를 만족시키지 못한다.
- Wizard 어댑터를 만들어 Client가 요구하는 인터페이스를 만족할 수 있도록 해준다.
## Figher
public interface Fighter {
public void attack();
public void defend();
public void goHome();
}
## Warrior
public class Warrior implements Fighter{
private String name;
private int level;
Warrior(String name, int level) {
this.name = name;
this.level = level;
}
public void showInfo() {
System.out.print("[ LEVEL "+ level + ", USERNAME " + name +"]");
}
@Override
public void attack() {
showInfo();
System.out.println( "Warrior 공격!");
}
@Override
public void defend() {
showInfo();
System.out.println("Warrior 방어");
}
@Override
public void goHome() {
showInfo();
System.out.println("Warrior 걸어서 귀환");
}
}
## Wizard
// 이미 게임에서 사용중인 클래스, 수정이 어렵다
public class Wizard {
private String name;
private int level;
Wizard(String name, int level){
this.name = name;
this.level = level;
}
public void showInfo() {
System.out.print("[ LEVEL "+ level + ", USERNAME " + name +"]");
}
public void shotMagicCloser(){
showInfo();
System.out.println("Wizard의 매직클로 공격!");
}
public void shield(){
showInfo();
System.out.println("Wizard의 방어막경계 생성!");
}
public void portal(){
showInfo();
System.out.println("Wizard의 포털이동!!");
}
}
## WizardAdapter
public class WizardAdapter implements Fighter{
Wizard wizard;
WizardAdapter(String name, int level){
wizard = new Wizard(name,level);
}
@Override
public void attack() {
wizard.shotMagicCloser();
}
@Override
public void defend() {
wizard.shield();
}
@Override
public void goHome() {
wizard.portal();
}
}
## Test
public class Test {
public static void main(String[] args) {
Fighter wizard = new WizardAdapter("타락파워마법사",200);
wizard.attack();
wizard.defend();
wizard.goHome();
System.out.println( " ======= ");
Fighter warrior = new Warrior("zl존최강전사",23);
warrior.attack();
warrior.defend();
warrior.goHome();
}
}
'• 독서 > Design Pattern' 카테고리의 다른 글
[디자인 패턴] 옵저버 패턴(Observer Pattern) (1) | 2022.10.04 |
---|---|
[디자인 패턴] 스테이트 패턴(State Pattern) (0) | 2022.10.02 |
[디자인 패턴] 컴포지트 패턴(Composite Pattern) (0) | 2022.09.30 |
[디자인패턴] 데코레이터 패턴(Decorator Pattern) (0) | 2022.09.27 |
[디자인패턴] 브릿지 패턴(Bridge Pattern) (0) | 2022.09.22 |