From 0cdab9b26118d49dcb533ad74c54cebdd6ae30f0 Mon Sep 17 00:00:00 2001 From: Choi Jae Woo <32676275+cjw23@users.noreply.github.com> Date: Fri, 25 Mar 2022 02:17:30 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[Add]=20=EC=96=B4=EB=8C=91=ED=84=B0=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20-=20=EC=98=88=EC=A0=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example-code.md" | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 "\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" diff --git "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" new file mode 100644 index 0000000..c1ef80e --- /dev/null +++ "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" @@ -0,0 +1,100 @@ +# 어댑터 패턴 적용 예제 + +어댑터 패턴의 개념은 이전 글에서 다루었기 때문에 생략했다. + +- 이전 글 : [https://dev-youngjun.tistory.com/210](https://dev-youngjun.tistory.com/210) + +실무에서는 어떤식으로 어댑터 패턴이 적용되는지 작성했다. + +## 1. 실무 요구사항 + +메일 발송을 위해 **솔루션 회사 A**와 계약하여 발송 프로세스를 개발하여 사용하고 있는데, **솔루션 회사 B**와 계약하여 메일을 발송하고 싶은 요구사항이 있다. + +현재까지 **솔루션 회사 A** 인터페이스를 사용한 수많은 클래스와 데이터들을 변경하고 싶지 않고, 현재 서비스 되고 있는 많은 부분을 변경하는 것은 위험하기 때문에, 기존 **솔루션 회사 A** 활용은 그대로 하고 B를 적용하고 싶다. + +그래서, 서로 다른 A사와 B사의 인터페이스를 함께 동작시킬 수 있도록 개발했으면 한다. + +## 2. Adapter 패턴 적용하기 + +솔루션 회사 A의 인터페이스는 아래와 같다. + +```java +// 솔루션 회사 A 인터페이스 +public interface MailSenderA { + void send(String sendInfo); +} + +// 기존에 구현되어있는 메일 발송 로직 +public class SolutionA implements MailSenderA { + + @Override + public void send(String sendInfo) { + System.out.println("A 솔루션 회사에서 메일 발송 : " + sendInfo); + } +} +``` + +당연하겠지만, 솔루션 회사 B는 인터페이스 규격이 회사 A와 다르다. + +```java +// 솔루션 회사 B 인터페이스 +public interface MailSenderB { + void sendApi(String sendInfo); +} + +// To-Be 메일 발송 로직 +public class SolutionB implements MailSenderB { + + @Override + public void sendApi(String sendInfo) { + System.out.println("B 솔루션 회사에서 메일 발송 : " + sendInfo); + } +} +``` + +여기에 클라이언트 입장에서 솔루션 회사 B를 범용성있게 적용하기 위해 Adapter 패턴을 활용할 수 있다. + +![adapter.png](https://user-images.githubusercontent.com/42997924/159971038-0e4cea2f-ebcc-46f7-b44c-441f746443af.png) + +```java +// Adapter Class +public class Adapter implements MailSenderA { + + // Adaptee(B회사) 생성자 주입 + private final MailSenderB mailSenderB; + + public Adapter(SolutionB newSolution) { + this.mailSenderB = newSolution; + } + + @Override + public void send(String sendInfo) { + System.out.print("Using Adapter >>> "); + // 기존 send를 호출 -> 솔루션 B의 sendApi 호출 연결 + mailSenderB.sendApi(sendInfo); + } +} +``` + +클라이언트는 기존에 사용하던 인터페이스 그대로 활용할 수 있게 됐다. + +```java +// 클라이언트 코드 +public class Client { + public static void main(String[] args) { + + MailSenderA senderA = new SolutionA(); + senderA.send("기존 발송 메일"); + + senderA = new Adapter(new SolutionB()); + senderA.send("TO-BE 발송 메일"); + } +} + +/* 실행 결과 +A 솔루션 회사에서 메일 발송 : 기존 발송 메일 +Using Adapter >>> B 솔루션 회사에서 메일 발송 : TO-BE 발송 메일 +*/ +``` + +> 기존에 있는 시스템(솔루션 A 활용)의 레거시 인터페이스를 새로운 인터페이스(솔루션 B)로 교체하는 경우에 기존 코드를 수정하지 않고 재사용성을 높일 수 있다. 새로운 써드파티 라이브러리가 추가되어도 어댑터 패턴은 유용하게 사용된다! \ No newline at end of file From 22098c12cffe17ac59bade01560d0fdd62ff5af7 Mon Sep 17 00:00:00 2001 From: dev-splin Date: Mon, 28 Mar 2022 17:41:22 +0900 Subject: [PATCH 2/4] =?UTF-8?q?UPDATE=20:=20=EC=96=B4=EB=8C=91=ED=84=B0=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20-=20=EC=A0=95=EB=A6=AC=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example-code.md" | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" index c1ef80e..4087b98 100644 --- "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" +++ "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" @@ -1,4 +1,22 @@ -# 어댑터 패턴 적용 예제 +## 1. 어댑터 패턴(Adapter Pattern) 이란? + +어댑터 패턴은 **기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴**을 말한다. + +일반적으로 어댑터 패턴은 110V 콘센트와 220V콘센트를 변환해주는 것을 예로 많이 든다다. 해당 예시를 개발 관점으로 얘기하자면, 클라이언트가 사용하는 인터페이스가 기존 코드와 다를 때, **기존 코드를 클라이언트 코드와 호환될 수 있게 처리해 주는 것으로 생각**하면 된다. + +![adapter](https://user-images.githubusercontent.com/79291114/160358256-30481999-0b13-425b-90e3-ffac32e6f843.PNG) + +- `Target` : `Client`가 사용하는 인터페이스 +- `Adaptee` : 기존에 사용하던 코드 +- `Adapter` : `Client`에서 `Adaptee`를 사용하기 위해 `Target`으로 변환 시켜 줌 + +결국 핵심은 **Adapter를 이용해 Adaptee를 Target으로 변환**해 준다는 것이다. + + + + + +## 2. 어댑터 패턴적용 예제 어댑터 패턴의 개념은 이전 글에서 다루었기 때문에 생략했다. From d522ea00432293d06764b146ca7266c6bf39bc69 Mon Sep 17 00:00:00 2001 From: dev-splin Date: Mon, 28 Mar 2022 18:01:45 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=20UPDATE=20:=20=EC=96=B4=EB=8C=91=ED=84=B0?= =?UTF-8?q?=20=ED=8C=A8=ED=84=B4=20-=20=EC=A0=95=EB=A6=AC=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example-code.md" | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" index 4087b98..84111e8 100644 --- "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" +++ "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" @@ -18,21 +18,19 @@ ## 2. 어댑터 패턴적용 예제 -어댑터 패턴의 개념은 이전 글에서 다루었기 때문에 생략했다. -- 이전 글 : [https://dev-youngjun.tistory.com/210](https://dev-youngjun.tistory.com/210) -실무에서는 어떤식으로 어댑터 패턴이 적용되는지 작성했다. +### 2-1. 요구사항 -## 1. 실무 요구사항 +메일 발송을 위해 `솔루션 회사 A`와 계약하여 발송 프로세스를 개발하여 사용하고 있는데, `솔루션 회사 B`와 계약하여 메일을 발송하고 싶은 요구사항이 있다. -메일 발송을 위해 **솔루션 회사 A**와 계약하여 발송 프로세스를 개발하여 사용하고 있는데, **솔루션 회사 B**와 계약하여 메일을 발송하고 싶은 요구사항이 있다. +현재 서비스 되고 있는 많은 부분을 변경하는 것은 위험하기 때문에, `솔루션 회사 A` 인터페이스를 사용한 수많은 클래스와 데이터들을 유지하면서 `솔루션 B`를 적용하고 싶다. -현재까지 **솔루션 회사 A** 인터페이스를 사용한 수많은 클래스와 데이터들을 변경하고 싶지 않고, 현재 서비스 되고 있는 많은 부분을 변경하는 것은 위험하기 때문에, 기존 **솔루션 회사 A** 활용은 그대로 하고 B를 적용하고 싶다. +그래서, 서로 다른 **A사와 B사의 인터페이스를 함께 동작시킬 수 있도록 개발**했으면 한다. -그래서, 서로 다른 A사와 B사의 인터페이스를 함께 동작시킬 수 있도록 개발했으면 한다. -## 2. Adapter 패턴 적용하기 + +### 2-2. Adapter 패턴 적용하기 솔루션 회사 A의 인터페이스는 아래와 같다. From c0f4dabc7ff9a07e0403157e482bd58ea281d2b2 Mon Sep 17 00:00:00 2001 From: dev-splin Date: Sun, 3 Apr 2022 21:30:28 +0900 Subject: [PATCH 4/4] =?UTF-8?q?UPDATE=20:=20=EC=96=B4=EB=8C=91=ED=84=B0=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20-=20=EC=A0=95=EB=A6=AC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example-code.md" | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" index 84111e8..34e3e19 100644 --- "a/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" +++ "b/\352\265\254\354\241\260/4\354\243\274\354\260\250-\354\226\264\353\214\221\355\204\260/example-code.md" @@ -18,8 +18,6 @@ ## 2. 어댑터 패턴적용 예제 - - ### 2-1. 요구사항 메일 발송을 위해 `솔루션 회사 A`와 계약하여 발송 프로세스를 개발하여 사용하고 있는데, `솔루션 회사 B`와 계약하여 메일을 발송하고 싶은 요구사항이 있다. @@ -68,7 +66,7 @@ public class SolutionB implements MailSenderB { } ``` -여기에 클라이언트 입장에서 솔루션 회사 B를 범용성있게 적용하기 위해 Adapter 패턴을 활용할 수 있다. +여기에 클라이언트 입장에서 솔루션 회사 B를 범용성있게 적용하기 위해 `Adapter 패턴`을 활용할 수 있다. ![adapter.png](https://user-images.githubusercontent.com/42997924/159971038-0e4cea2f-ebcc-46f7-b44c-441f746443af.png) @@ -113,4 +111,32 @@ Using Adapter >>> B 솔루션 회사에서 메일 발송 : TO-BE 발송 메일 */ ``` -> 기존에 있는 시스템(솔루션 A 활용)의 레거시 인터페이스를 새로운 인터페이스(솔루션 B)로 교체하는 경우에 기존 코드를 수정하지 않고 재사용성을 높일 수 있다. 새로운 써드파티 라이브러리가 추가되어도 어댑터 패턴은 유용하게 사용된다! \ No newline at end of file +> 기존에 있는 시스템(솔루션 A 활용)의 레거시 인터페이스를 새로운 인터페이스(솔루션 B)로 교체하는 경우에 기존 코드를 수정하지 않고 재사용성을 높일 수 있다. 새로운 써드파티 라이브러리가 추가되어도 어댑터 패턴은 유용하게 사용된다! + + + + + +## 3. 장/단점 + +### 장점 + +- 기존 코드(Adaptee)를 변경하지 않고 원하는 인터페이스(Target) 구현체를 만들어 재사용할 수 있다. + - 기존 코드를 변경하지 않고, 확장할 수 있다는 점에서 `OCP(Open Closed Principle)` 원칙에 가까운 패턴이다. +- 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다. + - 각각 하던 일에 집중할 수 있기 때문에 `SRP(Single Responsibility Principle)` 원칙에 가까운 패턴이다 + + + +### 단점 + +- 클래스가 많아지고 구조가 복잡해진다. + - 경우에 따라서는 기존 코드가 해당 인터페이스를 구현하도록 수정하는 것이 좋은 선택이 될 수도 있다. + + + + + +## 4. 마치며 + +사람인 데이터와 같이 다양한 데이터들이 얽혀있는 경우 기존 코드에 영향이 가지 않는 어댑터 패턴을 고려하는 것도 좋아보인다. \ No newline at end of file