어댑터라는 것은 우리 주변에서도 흔히 볼 수 있다. 대표적으로 110V 전용 가전 제품에 220V 어댑터를 끼워 사용하는 것이다.
어댑터를 보면 어댑터 패턴이 무엇인지 대충 감이 올 수도 있겠다.
이 패턴을 사용할만 한 경우를 만들어보면,
즉 '나'는 성능의 향상을 위해 포토 뷰어 엔진을 기존의 엔진에서 A 업체가 제공하는 엔진으로 바꿔야만 하는 상황이다.
이제 명세표를 보면 A엔진과 기존 엔진의 구조를 살표보자.
/* 내가 쓰는 엔진 명세 (MyLib) */ class MyLib { public: void printPhoto(String fileName) { ... } void printPhotoList(String[] listName) { ... } void deletePhoto(String fileName) { ... } void addPhoto(String fileName) { ... } }
/* A 엔진 명세 (ALib) */ class ALib { public:
void printPhoto(String fileName) { ... } void deletePhoto(String fileName) { ... } void addPhoto(String fileName) { ... } }
엔진이 완전히 같다면 좋을텐데 미묘하게 다른 구석이 있다. 차이가 있는 것은 제공 받은 엔진에서 printPhotoList() 가 없다는 것이다. 어쨋든 엔진 교체를 위해 코드 분석에 들어가보자. 아래 코드는 기존 엔진을 사용한 코드이다. 기존 엔진의 이름은 MyLib 이다.
/* 기존 코드 */ int main() { MyLib lib = new MyLib(); String photoList = { "abc.jpg" , "def.jpg" }; lib.printPhotoList(photoList); lib.printPhoto("abc.jpg"); lib.deletePhoto("abc.jpg"); lib.addPhoto("aaa.jpg"); }
자, 이제 함수명이 동일하니 한번 엔진을 바꿔보자.
/* 바뀐 코드 Ver.1 */ int main() { ALib lib = new ALib(); // change String photoList = { "abc.jpg" , "def.jpg" }; for(int i = 0 ; i < photoList.length; i++) // for문 추가됨
{ lib.printPhoto(photoList[i]); } lib.printPhoto("abc.jpg"); lib.deletePhoto("abc.jpg"); lib.addPhoto("aaa.jpg"); }
이제 프로그램은 잘 돌아갈거라고 생각이 되지만, 기본 로직에 변경이 생겼다. 바로 전에 없었던 for()이 들어가게 된 것이다. 물론 이 코드를 더 이상의 유지 보수를 하지 않을 예정이라면 이대로 놔둬도 상관없겠지만, 프로그램을 만들면 무조건 유지 보수를 해야하기 때문에 이렇게 두는 것은 좋지 않은 방법이다.
따라서 기본 로직을 그대로 이용할 수 있게끔 어댑터 패턴을 사용해보자.
class IPhotoEngine { public:
virtual void printPhoto(String fileName) = 0; virtual void printPhotoList(String[] listName) = 0;
virtual void deletePhoto(String fileName) = 0; virtual void addPhoto(String fileName) = 0; }
인터페이스 클래스를 만들었다. 이제 어댑터 클래스를 만들어보자.
class ALibAdapter : public IPhotoEngine { private: ALib lib; public: ALibAdapter( ALib lib ) { this.lib = lib; } void printPhoto(String fileName) { lib.printPhoto( fileName ); } void printPhotoList(String[] listName) { for(int i = 0 ; i < listName.length; i++) { lib.printPhoto( listName[i] ); } } void deletePhoto(String fileName) { lib.deletePhoto( fileName ); } void addPhoto(String fileName) { lib.addPhoto( fileName ); } }
이제 이 클래스를 사용해 보자.
/* 바뀐 코드 Ver.2 */ int main() { ALib alib = new ALib(); PhotoEngine lib = new ALibAdapter( alib ); String photoList = { "abc.jpg" , "def.jpg" }; lib.printPhotoList(photoList); lib.printPhoto("abc.jpg"); lib.deletePhoto("abc.jpg"); lib.addPhoto("aaa.jpg"); }
물론 ALib가 아닌 다른 엔진을 사용할 때에도 마찬가지로 IPhotoEngine 인터페이스를 포함한 어댑터 클래스를 만들기만 하면 언제든 로직을 재사용할 수 있다.
이것이 바로 어댑터 패턴을 사용하는 목적이기도 하다.
만약 기존엔진을 다시 써야하는 상황이 올때를 대비해서 기존 엔진의 어댑터 클래스를 만들어보자.
class MyLibAdapter : public PhotoEngine { private: MyLib lib; public: MyLibAdapter( MyLib lib ) { this.lib = lib; } void printPhoto(String fileName) { lib.printPhoto( fileName ); } void printPhotoList(String[] listName) { lib.printPhotoList( listName ); } void deletePhoto(String fileName) { lib.deletePhoto( fileName ); } void addPhoto(String fileName) { lib.addPhoto( fileName ); } }
그리고 간단하게 기존 엔진을 사용하도록 바꾸면 된다.
/* 바뀐 코드 Ver.3 */ int main() { MyLib myLib = new myLib(); PhotoEngine lib = new MyLibAdapter( myLib ); String photoList = { "abc.jpg" , "def.jpg" }; lib.printPhotoList(photoList); lib.printPhoto("abc.jpg"); lib.deletePhoto("abc.jpg"); lib.addPhoto("aaa.jpg"); }
'Basic Programming > Design Pattern' 카테고리의 다른 글
Design Pattern - 프록시 패턴(Proxy Pattern) (0) | 2017.12.18 |
---|---|
Design Pattern - 컴포지트 패턴(Composite Pattern) (0) | 2017.09.08 |
Design Pattern - 쓰레드에서 안전한 싱글턴 패턴(Thread-Safe Singleton Pattern) (0) | 2017.04.19 |
Design Pattern - 팩토리 패턴(Factory Pattern) (0) | 2017.03.08 |
Design Pattern - 옵저버 패턴(Observer Pattern) (0) | 2017.02.18 |