Post

⛓️ Java Design-Pattern β…£ - Template Method

⛓️ Java Design-Pattern β…£ - Template Method

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

Template Method νŒ¨ν„΄μ΄λž€?

  • μƒμœ„ ν΄λž˜μŠ€μ— λΌˆλŒ€λ‘œμ¨ ν…œν”Œλ¦Ώμ΄ 될 좔상 λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•˜κ³ , ν•˜μœ„ λ©”μ†Œλ“œμ—μ„œ 그것을 ꡬ체적으둜 κ΅¬ν˜„ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€.
  • μ–΄λŠ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„μ„ 달리 ν•˜λ”λΌλ„ μƒμœ„ 클래슀의 ν…œν”Œλ¦Ώμ— 따라 처리의 큰 흐름은 μ •ν•΄μ Έ μžˆλ‹€.
  • μ‹€μ œ ν…œν”Œλ¦Ώμ— λΉ„μœ ν•˜λ©΄, ν…œν”Œλ¦Ώ ꡬ멍을 톡해 μ–΄λ–€ ν˜•νƒœμ˜ λ¬ΈμžμΈμ§€ μ•Œ 수 μžˆμ§€λ§Œ μ–΄λ–€ 도ꡬλ₯Ό μ‚¬μš©ν•˜λŠλƒμ— 따라 색깔, λ˜λŠ” ꡬ체적인 λͺ¨μ–‘이 달라진닀.

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

  • λ¬Έμžμ—΄κ³Ό λ¬Έμžμ—΄ 리슀트λ₯Ό 좜λ ₯ν•˜λŠ” κ°„λ‹¨ν•œ ν”„λ‘œκ·Έλž¨μ΄λ‹€.
1
2
3
4
5
6
7
8
9
10
11
public abstract class AbstractDisplay {
	public abstract void open();
	public abstract void print();
	public abstract void close();
	
	public final void display() {
		open();
		print();
		close();
	}
}
  • AstractDisplay ν΄λž˜μŠ€λŠ” display() λ©”μ„œλ“œλ§Œ κ΅¬ν˜„λ˜μ–΄ 있으며 λ‚˜λ¨Έμ§€ μ„Έ 개의 λ©”μ„œλ“œλŠ” 좔상 λ©”μ„œλ“œλ‘œ μ •μ˜λ˜μ–΄ μžˆλ‹€.
  • 좔상 λ©”μ„œλ“œκ°€ μœ„μ—μ„œ μ„€λͺ…ν•œ ν…œν”Œλ¦Ώμ΄λ‹€.
  • μ„Έ 개의 좔상 λ©”μ„œλ“œλŠ” ν•˜μœ„ 클래슀λ₯Ό ν™•μΈν•˜μ§€ μ•ŠλŠ” ν•œ μ–΄λ–€ λ™μž‘μ„ ν•˜λŠ”μ§€ μ•Œ 수 μ—†λ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class OneLineDisplay extends AbstractDisplay {
	private String str;
	
	public OneLineDisplay(String str) {
		this.str = str;
	}
	
	@Override
	public void open() {
		System.out.println("<<");
	}
	
	@Override
	public void print() {
		System.out.println(str);
	}
	
	@Override
	public void close() {
		System.out.println(">>");
	}
}
  • OneLineDisplay ν΄λž˜μŠ€λŠ” 좔상 클래슀λ₯Ό 상속 λ°›μ•„ ν•œ μ€„μ˜ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MultiLineDisplay extends AbstractDisplay {
	private List<String> lines;
	
	public MultiLineDisplay(List<String> lines) {
		this.lines = lines;
	}
	
	@Override
	public void open() {
		System.out.println("=====================");
	}
	
	@Override
	public void print() {
		for (String str : lines) {
			System.out.println(str);
		}
	}
	
	@Override
	public void close() {
		System.out.println("=====================");
	}
}
  • MultiLineDisplay ν΄λž˜μŠ€λŠ” 좔상 클래슀λ₯Ό 상속 λ°›μ•„ μ—¬λŸ¬ μ€„μ˜ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
public class Main {
	public static void main(String[] args) {
		AbstractDisplay d1 = new OneLineDisplay("μ΄μŠˆμ— μ½”λ©˜νŠΈκ°€ λ‹¬λ ΈμŠ΅λ‹ˆλ‹€.");
		
		List<String> strList = new ArrayList<>(Arrays.asList({"μ•ˆλ…•ν•˜μ„Έμš”, CO-WORKINGμž…λ‹ˆλ‹€.", "νšŒμ›κ°€μž…μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€!", "κ°μ‚¬ν•©λ‹ˆλ‹€."}));
		AbstractDisplay d2 = new MultiLineDisplay(strList);
		
		d1.display();
		d2.display();
	}
}
  • 좔상 클래슀 λ³€μˆ˜μ— κ΅¬ν˜„μ²΄ μΈμŠ€ν„΄μŠ€λ₯Ό μ£Όμž…ν•˜μ—¬ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜λŠ” 메인 ν΄λž˜μŠ€μ΄λ‹€.

체크 포인트

βœ… 둜직 곡톡화

  • μƒμœ„ 클래슀의 ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ— μ•Œκ³ λ¦¬μ¦˜μ΄ κΈ°μˆ λ˜μ–΄ μžˆμœΌλ―€λ‘œ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œλŠ” μ•Œκ³ λ¦¬μ¦˜μ„ 일일이 κΈ°μˆ ν•  ν•„μš”κ°€ μ—†λ‹€.
  • κ°€λ Ή ν•΄λ‹Ή νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ§€ μ•Šκ³  κ΅¬ν˜„ 클래슀λ₯Ό μ—¬λŸ¬ 개 λ§Œλ“€μ–΄ 버린닀면 버그λ₯Ό λ°œκ²¬ν•  경우 λͺ¨λ“  클래슀λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•œλ‹€.
  • 그러면 또 ν…ŒμŠ€νŠΈν•΄μ•Ό ν•  λ²”μœ„κ°€ λ„“μ–΄μ§„λ‹€.
  • ν•˜μ§€λ§Œ ν•΄λ‹Ή νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄, ν…œν”Œλ¦Ώ λ©”μ„œλ“œλ§Œ μˆ˜μ •ν•˜λ©΄ λœλ‹€.

βœ… ν•˜μœ„ 클래슀λ₯Ό μƒμœ„ ν΄λž˜μŠ€μ™€ λ™μΌμ‹œν•œλ‹€.

  • instanceof λ“±μœΌλ‘œ ν•˜μœ„ 클래슀의 μ’…λ₯˜λ₯Ό νŠΉμ •ν•˜μ§€ μ•Šμ•„λ„ ν”„λ‘œκ·Έλž¨μ΄ λ™μž‘ν•œλ‹€.
  • μƒμœ„ ν΄λž˜μŠ€ν˜• λ³€μˆ˜μ— ν•˜μœ„ 클래슀의 μ–΄λ–€ 것을 λŒ€μž…ν•΄λ„ μ œλŒ€λ‘œ λ™μž‘ν•  수 있게 ν•˜λŠ” 원칙을 LSP라고 ν•œλ‹€.
  • The Liskov Substitution Principle의 쀀말이닀.

βœ… μƒμœ„ ν΄λž˜μŠ€μ—μ„œ ν•˜μœ„ 클래슀둜 μš”μ²­

  • 클래슀 계측에 κ΄€ν•΄ ν•™μŠ΅ν•  λ•Œ λ‹€μŒκ³Ό 같이 ν•˜μœ„ 클래슀 κ΄€μ μ—μ„œ 생각할 수 μžˆλ‹€.

    β€œμƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ •μ˜λœ λ©”μ†Œλ“œλ₯Ό ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μ΄μš©ν•  수 μžˆλ‹€.” β€œν•˜μœ„ ν΄λž˜μŠ€μ— μ•½κ°„μ˜ λ©”μ†Œλ“œλ₯Ό κΈ°μˆ ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œ μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•  수 μžˆλ‹€.” β€œν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œν•˜λ©΄ λ™μž‘μ„ λ³€κ²½ν•  수 μžˆλ‹€.”

  • μƒμœ„ 클래슀 κ΄€μ μ—μ„œλŠ” λ‹€μŒκ³Ό 같이 생각할 수 μžˆλ‹€.

    β€œν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ·Έ λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜κΈ°λ₯Ό κΈ°λŒ€ν•œλ‹€.” β€œν•˜μœ„ ν΄λž˜μŠ€μ— ν•΄λ‹Ή λ©”μ†Œλ“œ κ΅¬ν˜„μ„ μš”μ²­ν•œλ‹€.”

  • ν•˜μœ„ ν΄λž˜μŠ€μ—λŠ” μƒμœ„ 클래슀의 좔상 λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•  μ±…μž„μ΄ μžˆλŠ”λ°, 이λ₯Ό Subclass Responsibility라고 ν•œλ‹€.

βœ… 좔상 클래슀의 의의

  • 좔상 ν΄λž˜μŠ€λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μ—†λ‹€.
  • Template Method νŒ¨ν„΄μ„ μ΄ν•΄ν•˜λ©΄ 좔상 클래슀 λ‹¨κ³„μ—μ„œ 처리 흐름을 ν˜•μ„±ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€λŠ” 점을 μ•Œ 수 μžˆλ‹€.

βœ… μƒμœ„ ν΄λž˜μŠ€μ™€ ν•˜μœ„ 클래슀의 ν˜‘μ‘°

  • μƒμœ„ 클래슀의 μ†ŒμŠ€ μ½”λ“œκ°€ μ—†μœΌλ©΄ ν•˜μœ„ 클래슀 κ΅¬ν˜„μ΄ μ–΄λ €μšΈ 수 μžˆλ‹€.
  • μƒμœ„ ν΄λž˜μŠ€μ—μ„œ μ„ μ–Έλœ 좔상 클래슀λ₯Ό ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•  λ•ŒλŠ” κ·Έ λ©”μ„œλ“œκ°€ μ–΄λ–€ μ‹œμ μ— ν˜ΈμΆœλ˜λŠ”μ§€ 이해해야 ν•œλ‹€.
  • μƒμœ„ ν΄λž˜μŠ€μ— κΈ°μˆ ν•˜λŠ” λ‚΄μš©μ΄ λ§Žμ•„μ§€λ©΄ ν•˜μœ„ 클래슀λ₯Ό μž‘μ„±ν•˜κΈ° νŽΈν•΄μ§€μ§€λ§Œ ν•˜μœ„ 클래슀의 μžμœ λ„λŠ” λ–¨μ–΄μ§„λ‹€.
  • 반면 μƒμœ„ ν΄λž˜μŠ€μ— κΈ°μˆ ν•˜λŠ” λ‚΄μš©μ΄ 적어지면 ν•˜μœ„ 클래슀λ₯Ό μž‘μ„±ν•˜κΈ° μ–΄λ €μ›Œμ§€κ³ , 각각의 ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ 처리 기술이 쀑볡될 수 μžˆλ‹€.
  • Template Method νŒ¨ν„΄μ—μ„œλŠ” 처리 λ‚΄μš©μ˜ λΌˆλŒ€λŠ” μƒμœ„ ν΄λž˜μŠ€μ— κΈ°μˆ ν•˜κ³ , ꡬ체적인 λ‚΄μš©μ€ ν•˜μœ„ ν΄λž˜μŠ€μ— κΈ°μˆ ν•œλ‹€.
  • 그런데 μ–΄λ–€ 처리λ₯Ό μƒμœ„ ν΄λž˜μŠ€μ— 두고 μ–΄λ–€ 처리λ₯Ό ν•˜μœ„ ν΄λž˜μŠ€μ— λ‘˜ μ§€λ₯Ό κ·œμ •ν•œ 맀뉴얼이 μžˆλŠ” 것은 μ•„λ‹ˆκ³ , ν”„λ‘œκ·Έλž¨μ„ μ„€κ³„ν•˜λŠ” μ‚¬λžŒμ˜ λͺ«μ΄λ‹€.
This post is licensed under CC BY 4.0 by the author.