Adapter Pattern은 기존에 존재하는 클래스를 자기의 입맛에 맞게 특정한 클래스, 인터페이스를 통해서 바꾸어 줄 수 있는 패턴이다.
쉽게 예를 들면 노트북을 충전하려면 직류 12V가 필요한데 공급되는 건 교류 100V이다.
교류 100V를 AC 어댑터를 통해서 직류로 바꾸듯이 기존에 있는 것(교류 100V)을 특정한 클래스, 인터페이스(AC어댑터)를 통해서 12V로 바꾸어주는 것이 Adapter 패턴이다.
언제 사용하면 좋을까?
기존의 클래스를 건드리지 않고 다른 상황에 맞게 개조를 하여 사용해야할때 유용합니다.
기존의 코드들은 오류가 없다는 증거가 있기때문에 오류가 발생하면 어댑터에 잘못이 있음으로 기존의 코드는 보지 않아도 됩니다.
또는 기존의 클래스 없이 외부 api를 개조하여 사용할 때도 매우 편하게 사용할 수 있습니다.
예제는 class와 interface를 이용한 방법을 사용해보겠습니다.
UML
//기존의 클래스 (교류 100V)
public class Banner{ String name; public Banner(String name){ this.name = name; }
public void showWithParen(){ System.out.println("("+ this.name + ")"); }
public void showWithAster(){ System.out.println("*" + this.name +"*"); } }
//AC어댑터
public class BannerAdapter extends Print{ Banner banner; public BannerAdapter(Banner banner){ this.banner = banner; } public void printStrong(){ this.banner.showWithParen(); } public void printWeek(){ this.banner.showWithAster(); } }
//바뀐 결과(직류 12V)
public abstract class Print{ public abstract void printStrong(); public abstract void printWeek(); }
//Main
public class Main{ public static void main(String[] args){ Print print = new BannerAdapter(new Banner("Hello Hoony's Blog")); print.printStrong(); print.printWeek(); } }
받는 클래스를 Print를 사용한 이유는 Print 클래스에 있는 메소드만 사용할 수 있다고 제한을 두고 싶었습니다.
UML
//기존의 코드(Banner)
public class Banner{ String name; public Banner(String name){ this.name = name; }
public void printAster(){ System.out.println("*"+this.name+"*"); }
public void printParen(){ System.out.println("("+this.name+")"); } }
//AC어댑터
public class BannerAdapter extends Banner implements Print{ public BannerAdapter(String name){ super(name); } @Override public void printStrong() { printAster(); }
@Override public void printWeek() { printParen(); } }
//바뀐 결과
public interface Print{ public abstract void printStrong(); public abstract void printWeek(); }
//Main
public class Main{ public static void main(String[] args){ Print print = new BannerAdapter("hoony's blog"); print.printWeek(); print.printStrong(); } }
받는 클래스를 Print를 사용한 이유는 Print 인터페이스에 있는 메소드만 사용할 수 있다는 것을 강조하고 싶었습니다.
//Banner(기존의 클래스)
class Banner: def __init__(self, name): self.name = name