흔히 어댑터 패턴을 설명할 때 위의 어댑터의 역할을 예시로 많이 드는데요.
직류 15볼트로 동작하는 스마트폰을 교류 120볼트의 AC전원에 연결한다고 가정해볼게요.
이 때 AC 어댑터라는 장치를 사용하게 되는데요. AC 어댑터는 가정용 전원으로 제공되고 있는 교류 120볼트를 지금 필요한 직류 15볼트로 교환해 줍니다.
제공되고 있는 것과 필요한 것 사이를 연결 해주는 것이 바로 어댑터의 역할인데요.
어댑터의 사전적인 의미는 개조(adapt)시키는 것이라는 의미입니다. 그러니까 AC 어댑터의 역할은 직류 15볼트의 컴퓨터에 교류 100볼트의 환경에 맞게 바꾸는 것을 의미하는 것이죠.
이 처럼 프로그램 개발을 하다보면 이미 제공된 것을 그대로 사용할 수 없을 때 필요한 형태로 교환하고 사용하는 일이 자주 발생합니다.
이미 제공된 것과 필요한 것 사이의 차이를 없애 주는 디자인 패턴이 오늘 다뤄볼 Adpter패턴 입니다.
Adpter패턴은 Wrapper 패턴으로 불리기도 합니다. Wrappper는 사전적인 의미로 감싸는 것을 뜻하고 있습니다.
어떤 상품을 예쁜 포장지에 싸서 포장하여 상품으로 팔거나, 선물용으로 만드는 것처럼 무엇인가를 포장해서 다른 용도로 사용할 수 있게 교환해주는 것을 의미하기도 합니다.
보통 Adapter 패턴에는 두가지 종류가 있는데요.
- 클래스에 의한 Adpter패턴(상속을 사용한 패턴)
- 인스턴스에 의한 Adpter패턴(위임을 사용한 패턴)
먼저 상속을 사용한 Adpter패턴에 대해 알아보죠.
이번에 만들어볼 예제는 주어진 문자열 사이에 어떤 배너를 넣어서 출력하는 프로그램을 만들어 보겠습니다.
HelloWorld를 입력했을 때
[HelloWorld]
**HelloWorld**
와 같이 표시되도록 만들어보죠.
먼저 Banner 클래스를 만들어보죠.
package bami;
public class Banner {
private String string;
public Banner (String string) {
this.string = string;
}
public void ShowBrackets() {
System.out.println("[" + string + "]");
}
public void ShowStar() {
System.out.println("**" + string + "**");
}
}
Banner는 현수막이라는 의미이기 때문에 Banner라고 만들었습니다.
이 Banner 클래스는 위에서 말씀 드렸던 이미 제공된 것을 의미합니다.
대괄호를 영어로 square brackets이기 때문에 뒷글자의 brackets만 따왔고, star는 asterisk도 있지만 좀 더 짧은 star로 지었습니다.
그 다음은 StringPrint 인터페이스를 만들어 봅시다.
package bami;
public interface PrintString {
public abstract void PrintBrackets();
public abstract void PrintStar();
}
PrintString이라는 인터페이스에서는 [string], **string** 형식으로 표시하기 위한 메소드 들이 선언되어 있는데 위와 다른점은 이 인터페이스가 교류 120볼트를 직류 15볼트로 교환해 주는 어댑터를 만드는 역할을 한다는 점입니다.
그래서 Banner클래스를 사용하여 PrintString 인터페이스를 충족시켜주는 클래스를 만듭니다.
그 후 PrintBanner클래스를 만들어 봅시다.
package bami;
public class PrintBanner extends Banner implements PrintString {
public PrintBanner(String string) {
super(string);
}
public void PrintBrackets() {
ShowBrackets();
}
public void PrintStar() {
ShowStar();
}
}
PrintBanner 클래스가 그 어댑터 역할을 담당하여 Banner클래스를 상속해서 구현하고자 하는 PrintString 인터페이스를 구현해줍니다.
이제 Main 클래스를 만들어 보겠습니다.
package bami;
public class Main {
public static void main(String[] args) {
PrintString p = new PrintBanner("HelloWorld");
p.PrintBrackets();
p.PrintStar();
}
}
Main에서 String값을 보내주면 해당 String에 맞게 Banner라는 클래스에서 String사이에 [string], **string** 형식으로 붙여 줍니다.
이번에는 위에서는 상속을 사용했다면 이번에는 위임을 사용한 Adapter패턴으로 만들어 보겠습니다.
위임이라는 단어가 생소 할 수 있는데 위임은 누군가에게 맡긴다는 의미로 생각하시면 됩니다.
Java에서는 어떤 메소드의 처리를 다른 인스턴스의 메소드에게 맡깁니다.
Main 클래스와 Banner클래스는 위와 동일하지만 PrintString인터페이스를 클래스로 가정하여 Banner 클래스를 사용해 PrintString 클래스와 동일한 메소드를 갖는 클래스를 만들어 봅시다.
먼저 PrintString클래스를 수정해주도록 하겠습니다.
package bami;
public abstract class PrintString {
public abstract void PrintBrackets();
public abstract void PrintStar();
}
그 후 PrintBanner 클래스를 수정해줍니다.
package bami;
public class PrintBanner extends PrintString {
private Banner banner;
public PrintBanner(String string) {
this.banner = new Banner(string);
}
public void PrintBrackets() {
banner.ShowBrackets();
}
public void PrintStar() {
banner.ShowStar();
}
}
Java에서는 단일 상속으로 2개의 클래스를 동시에 상속 할 수 없기 때문에 PrintBanner 클래스를 PrintString와 Banner 클래스를 하위 클래스로 둘 수 없습니다. 그래서 banner 필드에서 Banner 클래스의 인스턴스를 가지고, 이 인스턴스는 PrintBanner의 생성자에서 생성하여 각 메소드들은 banner 필드를 매개로 메소드들을 호출하도록 했습니다.
그래서 이번에는 필드를 경유해서 호출하는 위임을 하여 자신이 처리하는 것이 아니라 별도의 인스턴스들이 각 메소드들에게 위임하고 있는 형태입니다.
실행 결과는 역시 동일합니다.
풀소스
Banner.java
package bami;
public class Banner {
private String string;
public Banner (String string) {
this.string = string;
}
public void ShowBrackets() {
System.out.println("[" + string + "]");
}
public void ShowStar() {
System.out.println("**" + string + "*");
}
}
PrintBanner.java
package bami;
public class PrintBanner extends PrintString {
private Banner banner;
public PrintBanner(String string) {
this.banner = new Banner(string);
}
public void PrintBrackets() {
banner.ShowBrackets();
}
public void PrintStar() {
banner.ShowStar();
}
}
PrintString.java
package bami;
public abstract class PrintString {
public abstract void PrintBrackets();
public abstract void PrintStar();
}
Main.java
package bami;
public class Main {
public static void main(String[] args) {
PrintString p = new PrintBanner("HelloWorld");
p.PrintBrackets();
p.PrintStar();
}
}
참고 : Java 언어로 배우는 디자인 패턴 입문
'프로그래밍(Basic) > 디자인 패턴(Java)' 카테고리의 다른 글
[바미] Singleton 패턴에 대해 알아봅시다. (0) | 2021.09.23 |
---|---|
[바미] Factory Method에 대해 알아봅시다. (0) | 2021.09.21 |
[바미] 템플릿 메소드(Template Method) 패턴에 대해 알아봅시다. (0) | 2021.09.15 |
[바미] Iterator패턴에 대해 알아봅시다. (0) | 2021.08.17 |
[바미] UML에 대해 알아봅시다. (0) | 2021.08.16 |