Post

⛓️ Java Design-Pattern β…’ - Adapter

⛓️ Java Design-Pattern β…’ - Adapter

πŸ“— γ€ŽJAVA μ–Έμ–΄λ‘œ λ°°μš°λŠ” λ””μžμΈ νŒ¨ν„΄ : μ‰½κ²Œ λ°°μš°λŠ” GoF의 23κ°€μ§€ λ””μžμΈ νŒ¨ν„΄γ€λ₯Ό 읽고 μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€.

Adapter νŒ¨ν„΄μ΄λž€?

  • 직λ₯˜ 12 볼트둜 λ™μž‘ν•˜λŠ” λ…ΈνŠΈλΆμ„ ꡐλ₯˜ 100 볼트 AC 전원에 μ—°κ²°ν•  λ•Œ μš°λ¦¬λŠ” AC μ–΄λŒ‘ν„°λΌλŠ” μž₯치λ₯Ό μ‚¬μš©ν•œλ‹€.
  • 제곡된 것과 ν•„μš”ν•œ 것 κ·Έ μ‚¬μ΄μ—μ„œ AC μ–΄λŒ‘ν„°κ°€ Adapter 역할을 ν•˜λŠ” 것이닀.
  • Adapter νŒ¨ν„΄μ€ ν”„λ‘œκ·Έλž˜λ° μ°¨μ›μ—μ„œλ„ 이미 제곡된 μ½”λ“œλ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 없을 λ•Œ ν•„μš”ν•œ ν˜•νƒœλ‘œ λ³€ν™˜ν•˜μ—¬ μ΄μš©ν•˜λŠ” 경우 μ‚¬μš©ν•œλ‹€.
  • κ·Έλž˜μ„œ Adapter νŒ¨ν„΄μ€ Wrapper νŒ¨ν„΄μ΄λΌκ³  ν‘œν˜„ν•œλ‹€.
  • Adapter νŒ¨ν„΄μ€ λ‹€μŒ 두 κ°€μ§€ λ°©λ²•μœΌλ‘œ κ΅¬ν˜„ν•  수 μžˆλ‹€.
    1. 클래슀 상속을 μ΄μš©ν•˜μ—¬ 쀑간 역할을 μˆ˜ν–‰ν•œλ‹€.
    2. 쀑간 역할을 μΈμŠ€ν„΄μŠ€μ— μœ„μž„ν•œλ‹€.

예제 ν”„λ‘œκ·Έλž¨

  • λ‹€μŒ ν”„λ‘œκ·Έλž¨μ€ μ—…λ¬΄μ˜ μ„ΈλΆ€ 정보λ₯Ό 좜λ ₯ν•˜λŠ” λ·°μ–΄λ₯Ό κ΅¬ν˜„ν•œ 것이닀.
  • μœ„μ—μ„œ μ–ΈκΈ‰ν•œ 클래슀λ₯Ό μƒμ†ν•˜λŠ” 방법과 μœ„μž„μ„ μ‚¬μš©ν•˜λŠ” 방법 λͺ¨λ‘ μ‚΄νŽ΄λ³Ό 것이닀.

βœ… 클래슀λ₯Ό μƒμ†ν•˜λŠ” 방법

1
2
3
4
5
6
7
8
9
10
11
public class TaskViewerΒ Β {
	private Task task;
	
	public TaskViewer(Task task) {
		this.task = task;
	}
	
	public void showTaskInfo() {
		System.out.println(task.getName());
	}
}
  • TaskViewer ν΄λž˜μŠ€λŠ” μš°λ¦¬μ—κ²Œ μ£Όμ–΄μ§„ 것이라고 κ°€μ •ν•œλ‹€.
  • ν•΄λ‹Ή ν΄λž˜μŠ€μ— μ‘΄μž¬ν•˜λŠ” showTaskInfo() λ©”μ„œλ“œλŠ” μ—…λ¬΄μ˜ μ΄λ¦„λ§Œ μ•Œ 수 μžˆμœΌλ―€λ‘œ μ‚¬μš©μž μž…μž₯μ—μ„œλŠ” 얻을 수 μžˆλŠ” 정보가 μ œν•œμ μ΄λ‹€.
1
2
3
public interface UpgradedTaskViewer {
	public abstract void showDetailInfo();
}
  • UpgradedTaskViewer μΈν„°νŽ˜μ΄μŠ€λŠ” μš°λ¦¬κ°€ ν•„μš”λ‘œ ν•˜λŠ” 것이닀.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TaskDetailViewer extends TaskViewer implements upgradedTaskViewer {
	public TaskDetailViewer(Task task) {
		super(task);
	}
	
	@Override
	public void showDetailInfo() {
		System.out.println("=============== 업무 ===============");
		
		showTaskInfo();
		System.out.println(task.getDescription());
		
		System.out.println("============= ν•˜μœ„μ—…λ¬΄ =============");
		
		List<SubTask> subTasks = task.getSubTasks();
		for (SubTask subTask : subTasks) {
			System.out.println(subTask.getName());
		}
	}
}
  • TaskDetailViewer ν΄λž˜μŠ€λŠ” μ–΄λŒ‘ν„° 역할을 ν•œλ‹€.
  • TaskViewer 클래슀λ₯Ό μƒμ†ν•˜λŠ” λ™μ‹œμ— upgradeTaskViewer μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€.
  • showDetailInfo() λ©”μ„œλ“œλŠ” TaskViewer의 showTaskInfo() λ©”μ„œλ“œμ— 살을 λΆ™μ—¬ μ‚¬μš©μžμ—κ²Œ λ”μš± ν’λΆ€ν•œ 정보λ₯Ό μ œκ³΅ν•œλ‹€.
1
2
3
4
5
6
7
public class Main {
	public static void main(String[] args) {
		Task task = new Task(); // 정보가 μΈμŠ€ν„΄μŠ€ ν•„λ“œμ— μ΄ˆκΈ°ν™”λ˜μ–΄ μžˆλ‹€κ³  κ°€μ •
		UpgradedTaskViewer u = new TaskDetailViewer(task);
		u.showDetailInfo();
	}
}
  • 메인 ν΄λž˜μŠ€μ—λŠ” TaskViewer ν΄λž˜μŠ€μ™€ TaskDetailViewer 클래슀의 κ΅¬ν˜„μ€ μ™„μ „νžˆ 숨겨져 μžˆλ‹€.Β 
  • κ·ΈλŸ¬λ―€λ‘œ 메인 클래슀의 μˆ˜μ • 없이 UpgradedTaskViewer μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„μ„ λ³€κ²½ν•  수 μžˆλ‹€.

βœ… μœ„μž„μ„ μƒμ†ν•˜λŠ” 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TaskViewerΒ Β {
	private Task task;
	
	public TaskViewer(Task task) {
		this.task = task;
	}
	
	public void showTaskInfo() {
		System.out.println(task.getName());
	}
	
	public void getTask() {
		return this.task;
	}
}
  • TaskViewer ν΄λž˜μŠ€λŠ” 상속을 μ‚¬μš©ν•œ 방법과 λ™μΌν•˜λ‹€.
  • κ΅¬ν˜„ 방법이 λ°”λ€Œλ”λΌλ„ μš°λ¦¬κ°€ ν•„μš”ν•œ 건 λ°”λ€Œμ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.Β 
1
2
3
public abstract class UpgradedTaskViewer {
	public abstract void showDetailInfo();
}
  • UpgradedTaskViewer ν΄λž˜μŠ€λŠ” μΈν„°νŽ˜μ΄μŠ€μ—μ„œ 좔상 클래슀둜 λ°”λ€Œμ—ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TaskDetailViewer extends UpgradedTaskViewer {
	private TaskViewer taskViewer;
	
	public TaskDetailViewer(Task task) {
		this.taskViewer = new TaskViewer(task);
	}
	
	@Override
	public void showDetailInfo() {
		System.out.println("=============== 업무 ===============");
		
		taskViewer.showTaskInfo();
		System.out.println(taskViewer.getTask().getDescription());
		
		System.out.println("============= ν•˜μœ„μ—…λ¬΄ =============");
		
		List<SubTask> subTasks = taskViewer.getTask().getSubTasks();
		for (SubTask subTask : subTasks) {
			System.out.println(subTask.getName());
		}
	}
}
  • TaskDetailViewer ν΄λž˜μŠ€λŠ” μ–΄λŒ‘ν„° 역할을 ν•œλ‹€.
  • TaskViewer 클래슀λ₯Ό ν•„λ“œλ‘œ κ°€μ§€λ©° ν•΄λ‹Ή ν•„λ“œμ— λͺ¨λ“  κ±Έ μœ„μž„ν•œλ‹€.
1
2
3
4
5
6
7
public class Main {
	public static void main(String[] args) {
		Task task = new Task(); // 정보가 μΈμŠ€ν„΄μŠ€ ν•„λ“œμ— μ΄ˆκΈ°ν™”λ˜μ–΄ μžˆλ‹€κ³  κ°€μ •
		UpgradedTaskViewer u = new TaskDetailViewer(task);
		u.showDetailInfo();
	}
}
  • 메인 ν΄λž˜μŠ€λ„ 두 방법이 λ™μΌν•˜λ‹€.

체크 포인트

βœ… μ–΄λ–€ κ²½μš°μ— μ‚¬μš©ν• κΉŒ?

  • ν”„λ‘œκ·Έλž˜λ°μ€ 늘 λ°±μ§€μƒνƒœμ—μ„œ μ‹œμž‘ν•˜λŠ” 것은 μ•„λ‹ˆλ‹€.
  • 이미 μ‘΄μž¬ν•˜λŠ” 클래슀λ₯Ό μ΄μš©ν•˜λŠ” κ²½μš°λ„ ν”ν•˜λ‹€.
  • AdapterΒ νŒ¨ν„΄μ€ κΈ°μ‘΄ 클래슀λ₯Ό 감싸 ν•„μš”ν•œ 클래슀λ₯Ό λ§Œλ“€μ–΄ λ‚΄λŠ” νŒ¨ν„΄μ΄λ‹€.
  • 버그가 λ°œμƒν•˜λ”λΌλ„ κΈ°μ‘΄ ν΄λž˜μŠ€μ—λŠ” 버그가 μ—†λŠ” 것을 μ•Œκ³  μžˆμœΌλ―€λ‘œΒ AdapterΒ μ—­ν• μ˜ 클래슀λ₯Ό μ€‘μ μ μœΌλ‘œ μ‚΄νŽ΄λ³΄λ©΄ 되기 λ•Œλ¬Έμ— ν”„λ‘œκ·Έλž¨ 검사가 맀우 νŽΈν•΄μ§„λ‹€.

βœ… λ‹¨μˆœνžˆ κΈ°μ‘΄ 클래슀λ₯Ό μˆ˜μ •ν•˜λ©΄ λ˜μ§€ μ•Šλ‚˜?

  • λ§Œμ•½ 이미 λ§Œλ“€μ–΄μ§„ ν΄λž˜μŠ€κ°€ 있고 μƒˆλ‘œμš΄Β API에 λ§žμΆ˜λ‹€κ³  κ°€μ •ν•˜λ©΄ μš°λ¦¬λ“€μ€ κΈ°μ‘΄ 클래슀λ₯Ό λ§Œμ Έμ„œ μˆ˜μ •ν•˜κ³  λ§Œλ‹€.
  • ν•˜μ§€λ§Œ κ·Έλ ‡κ²Œ ν•˜λ©΄ λ™μž‘ ν…ŒμŠ€νŠΈκ°€ 이미 λλ‚¬μŒμ—λ„ 손을 λŒ”μœΌλ‹ˆ λ‹€μ‹œ ν…ŒμŠ€νŠΈν•΄μ•Ό ν•œλ‹€.
  • AdapterΒ νŒ¨ν„΄μ˜ λͺ©μ μ€ κΈ°μ‘΄ 클래슀λ₯Ό μ „ν˜€ μˆ˜μ •ν•˜μ§€ μ•Šκ³  μƒˆλ‘œμš΄Β APIλ₯Ό κ°œλ°œν•˜λŠ” 것이닀.
  • λ˜ν•œ κΈ°μ‘΄ 클래슀의 μ†ŒμŠ€ μ½”λ“œκ°€ λ°˜λ“œμ‹œ ν•„μš”ν•œ 것은 μ•„λ‹ˆκ³  κΈ°μ‘΄ 클래슀의 μ‚¬μ–‘λ§Œ μ•Œλ©΄ μƒˆλ‘œμš΄ 클래슀λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

βœ… 버전 μ—…κ·Έλ ˆμ΄λ“œμ™€ ν˜Έν™˜μ„±

  • μ†Œν”„νŠΈμ›¨μ–΄λŠ” 버전 μ—…κ·Έλ ˆμ΄λ“œκ°€ ν•„μš”ν•˜λ‹€.
  • ν•˜μ§€λ§Œ μ΄λ•Œ κ΅¬λ²„μ „κ³Όμ˜ ν˜Έν™˜μ„±μ΄ λ¬Έμ œκ°€ λœλ‹€.
  • AdapterΒ νŒ¨ν„΄μ€ 신버전과 ꡬ버전을 κ³΅μ‘΄μ‹œν‚€κ³  μœ μ§€λ³΄μˆ˜κΉŒμ§€ νŽΈν•˜κ²Œ ν•  수 μžˆλ„λ‘ 도와쀀닀.

βœ… 동 λ–¨μ–΄μ§„ 클래슀

  • AdapterΒ μ—­ν• κ³ΌΒ TargetΒ μ—­ν• μ˜ κΈ°λŠ₯이 λ„ˆλ¬΄ 동 λ–¨μ–΄μ§„ κ²½μš°μ—λŠ”Β AdapterΒ νŒ¨ν„΄μ„ μ‚¬μš©ν•  수 μ—†λ‹€.

βœ… 상속과 μœ„μž„, μ–΄λŠ μͺ½μ„ μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

  • 일반적으둜 상속을 μ‚¬μš©ν•˜λŠ” 것보닀 μœ„μž„μ„ μ‚¬μš©ν•˜λŠ” 편이 λ¬Έμ œκ°€ 적닀.Β 
  • κ·Έ μ΄μœ λŠ” μƒμœ„ 클래슀의 λ‚΄λΆ€ λ™μž‘μ„ μžμ„Ένžˆ λͺ¨λ₯΄λ©΄ 상속을 효과적으둜 μ‚¬μš©ν•˜κΈ° μ–΄λ €μš΄ κ²½μš°κ°€ 많기 λ•Œλ¬Έμ΄λ‹€.

회고

  • 사싀 예제 ν”„λ‘œκ·Έλž¨μ΄ μ±…μ˜ λ‚΄μš©κ³ΌλŠ” λ‹€λ₯΄λ‹€.
  • 책에 μžˆλŠ” μ½”λ“œλ₯Ό κ·Έμ € 타이핑할 λ•Œλ³΄λ‹€ 이 편이 λ”μš± 이해가 잘 λ˜λŠ” 것 κ°™λ‹€.
This post is licensed under CC BY 4.0 by the author.