λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

πŸ“šμ½μ€ μ±… 정리/μžλ°” 객체지ν–₯ 원리와 이해

[μŠ€ν”„λ§ μž…λ¬Έμ„ μœ„ν•œ μžλ°” 객체 지ν–₯의 원리와 이해] 6μž₯ : μŠ€ν”„λ§μ΄ μ‚¬λž‘ν•œ λ””μžμΈ νŒ¨ν„΄

'객체지ν–₯의 4λŒ€ νŠΉμ„±'은 객체지ν–₯을 잘 μ‚¬μš©ν•˜κΈ°μœ„ν•œ '도ꡬ'이닀.

'객체지ν–₯의 5λŒ€ 원칙'은 μ΄λŸ¬ν•œ 도ꡬλ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•˜λŠ” μ›μΉ™μœΌλ‘œ λ³Ό 수 μžˆλ‹€.

κ·Έλ ‡λ‹€λ©΄ λ””μžμΈνŒ¨ν„΄μ€ 무엇에 λΉ„μœ ν•  수 μžˆμ„κΉŒ?

 

'λ””μžμΈ νŒ¨ν„΄'은 λ ˆμ‹œν”Όμ— λΉ„μœ ν•  수 μžˆλ‹€. 

μ‹€μ œ 개발 ν˜„μž₯μ—μ„œ λΉ„μ¦ˆλ‹ˆμŠ€ μš”κ΅¬ 사항을 μ²˜λ¦¬ν•˜λ©΄μ„œ λ§Œλ“€μ–΄μ§„ λ‹€μ–‘ν•œ ν•΄κ²°μ±… 쀑 λ§Žμ€ μ‚¬λžŒλ“€μ΄ μΈμ •ν•œ '베슀트  ν”„λ ‰ν‹°μŠ€'λ₯Ό μ •λ¦¬ν•œ 것이닀. (λ””μžμΈ νŒ¨ν„΄μ€ λ‹Ήμ—°νžˆ 객체 지ν–₯ νŠΉμ„±κ³Ό 섀계 원칙을 기반으둜 ꡬ성)

 

-> μŠ€ν”„λ§ μ—­μ‹œ λ‹€μ–‘ν•œ λ””μžμΈ νŒ¨ν„΄μ„ ν™œμš©ν•˜κ³  μžˆλ‹€!

 

* μŠ€ν”„λ§μ˜ 곡식적 μ •μ˜ : "μžλ°” μ—”ν„°ν”„λΌμ΄μ¦ˆ κ°œλ°œμ„ νŽΈν•˜κ²Œ ν•΄μ£ΌλŠ” μ˜€ν”ˆμ†ŒμŠ€ κ²½λŸ‰κΈ‰ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ ˆμž„μ›Œν¬"

 

λ””μžμΈ νŒ¨ν„΄μ€ 객체 지ν–₯의 νŠΉμ„± 쀑 '상속', 'μΈν„°νŽ˜μ΄μŠ€', 'ν•©μ„±'을 μ΄μš©ν•œλ‹€. (합성은 객체λ₯Ό μ†μ„±μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 것)

 

μ–΄λŒ‘ν„° νŒ¨ν„΄ (Adapter Pattern)

ν•œ 클래슀의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μ‚¬μš©ν•˜κ³ μžν•˜λŠ” λ‹€λ₯Έ μΈν„°νŽ˜μ΄μŠ€λ‘œ λ³€ν™˜ν•œλ‹€.
μ–΄λŒ‘ν„°λ₯Ό μ΄μš©ν•˜λ©΄ μΈν„°νŽ˜μ΄μŠ€ ν˜Έν™˜μ„± 문제 λ•Œλ¬Έμ— 같이 μ“Έ 수 μ—†λŠ” ν΄λž˜μŠ€λ“€μ„ μ—°κ²°ν•΄μ„œ μ“Έ 수 μžˆλ‹€,

 

ODBC/JDBCκ°€ μ–΄λŒ‘ν„° νŒ¨ν„΄μ„ μ΄μš©ν•΄ λ‹€μ–‘ν•œ λ°μ΄ν„°λ² μ΄μŠ€ μ‹œμŠ€ν…œμ„ λ‹¨μΌν•œ μΈν„°νŽ˜μ΄μŠ€λ‘œ μ‘°μž‘ν•  수 있게 ν•΄μ€€λ‹€.

'μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜' - 'μ–΄λŒ‘ν„°' - 'μ‹€μ œ κ΅¬ν˜„μ²΄'

 

μ–΄λŒ‘ν„° νŒ¨ν„΄ μ‚¬μš©

public class AdapterServicA {
	ServiceA sa1 = new ServiceA();

	void runService() {
		sa1.runServiceA();
	}
}

public class AdapterServicB {
	ServiceB sb1 = new ServiceB();

	void runService() {
		sb1.runServiceB();
	}
}

메인 λ©”μ„œλ“œ

public class ClientWithAdapter {
	public static void main(String[] args) {
		AdapterServicA asa1 = new AdapterServicA();
		AdapterServicB asb1 = new AdapterServicB();

		asa1.runService();
		asb1.runService();
	}
}

μ–΄νƒ­ν„°μ—μ„œ λ™μΌν•œ μ΄λ¦„μ˜ runService()λ₯Ό μ‚¬μš©ν•΄μ„œ 각각의 runServiceXλ₯Ό ν˜ΈμΆœν•˜κ³  μžˆλ‹€.

 

μ’€ 더 κ°œμ„ ν•΄λ³΄μžλ©΄ μ–΄νƒ­ν„°κ°€ νŠΉμ • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ²Œ ν•΄μ„œ ν•˜λ‚˜μ˜ μΈν„°νŽ˜μ΄μŠ€μ—μ„œ μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ„ 톡해 λ˜‘κ°™μ€ λ©”μ„œλ“œλ‘œ 각각 λ‹€λ₯Έ

κ΅¬ν˜„μ²΄μ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€.

 

"ν˜ΈμΆœλ‹Ήν•˜λŠ” μͺ½μ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” μͺ½μ˜ μ½”λ“œμ— λŒ€μ‘ν•˜λ„λ‘ 쀑간에 λ³€ν™˜κΈ°λ₯Ό 톡해 ν˜ΈμΆœν•˜λŠ” νŒ¨ν„΄"

ν”„λ‘μ‹œ νŒ¨ν„΄(Proxy Pattern)

ν”„λ‘μ‹œλŠ” λŒ€λ¦¬μžλΌλŠ” μ˜λ―Έμ΄λ‹€. λŒ€λ¦¬μžλΌκ³  ν•˜λ©΄ λ‹€λ₯Έ λˆ„κ΅°κ°€λ₯Ό λŒ€μ‹ ν•΄ κ·Έ 역할을 μˆ˜ν–‰ν•˜λŠ” 쑴재λ₯Ό λ§ν•œλ‹€.

ν”„λ‘μ‹œ νŒ¨ν„΄ μ‚¬μš©

  • 클래슀
public interface IService {
	String runSomething();
}

public class Proxy implements IService {
	IService service1;

	public String runSomething() {
		System.out.println("ν˜ΈμΆœμ— λŒ€ν•œ 흐름 μ œμ–΄κ°€ μ£Όλͺ©μ , λ°˜ν™˜ κ²°κ³Όλ₯Ό κ·ΈλŒ€λ‘œ 전달");

		service1 = new Service();
		return service1.runSomething();
	}
}

public class Service implements IService {
	public String runSomething() {
		return "μ„œλΉ„μŠ€ 짱!!!";
	}
}

 

  • 메인 λ©”μ„œλ“œ
public class ClientWithProxy {
	public static void main(String[] args) {
		// ν”„λ‘μ‹œλ₯Ό μ΄μš©ν•œ 호좜
		IService proxy = new Proxy();
		System.out.println(proxy.runSomething());
	}
}

ν”„λ‘μ‹œ νŒ¨ν„΄μ„ μ μš©ν•œ ν›„ μ‹œν€€μŠ€ λ‹€μ΄μ–΄κ·Έλž¨

μ„œλΉ„μŠ€ 객체가 λ“€μ–΄κ°ˆ μžλ¦¬μ— λŒ€λ¦¬μž 객체λ₯Ό λŒ€μ‹  νˆ¬μž…ν•œλ‹€.

ν”„λ‘μ‹œ νŒ¨ν„΄μ˜ μ€‘μš” 포인트

  • λŒ€λ¦¬μž(ν”„λ‘μ‹œ)λŠ” μ‹€μ œ μ„œλΉ„μŠ€μ™€ 같은 μ΄λ¦„μ˜ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„
  • λŒ€λ¦¬μžλŠ” μ‹€μ œ μ„œλΉ„μŠ€μ— λŒ€ν•œ μ°Έμ‘° λ³€μˆ˜λ₯Ό κ°–λŠ”λ‹€. (ν•©μ„±)
  • λŒ€λ¦¬μžλŠ” μ‹€μ œ μ„œλΉ„μŠ€μ˜ 같은 이름을 가진 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ³  κ·Έ 값을 ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ λ°˜ν™˜ν•œλ‹€.
  • λŒ€λ¦¬μžλŠ” μ‹€μ œ μ„œλΉ„μŠ€μ˜ λ©”μ„œλ“œ 호좜 전후에 λ³„λ„μ˜ λ‘œμ§μ„ μˆ˜ν–‰ν•  μˆ˜λ„ μžˆλ‹€.
ν”„λ‘μ‹œ νŒ¨ν„΄μ€ μ‹€μ œ μ„œλΉ„μŠ€μ˜ λ°˜ν™˜κ°’μ€ λ³€κ²½ν•˜μ§€ μ•Šκ³  μ œμ–΄μ˜ 흐름을 λ³€κ²½ν•˜κ±°λ‚˜ λ‹€λ₯Έ λ‘œμ§μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄

원본에 μž₯식을 λ”ν•˜λŠ” νŒ¨ν„΄!

 

ν”„λ‘μ‹œ νŒ¨ν„΄κ³Ό κ΅¬ν˜„ 방법이 κ°™μœΌλ‚˜ μ΅œμ’…μ μœΌλ‘œ λ°˜ν™˜ν•˜λŠ” λ°˜ν™˜κ°’μ— μž₯식을 λ§μž…νžŒλ‹€.

 

public class Decoreator implements IService {
	IService service;

	public String runSomething() {
		System.out.println("ν˜ΈμΆœμ— λŒ€ν•œ μž₯식 μ£Όλͺ©μ , ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ λ°˜ν™˜ 결과에 μž₯식을 λ”ν•˜μ—¬ 전달");

		service = new Service();
		return "정말" + service.runSomething();
	}
}

λ°˜ν™˜ 값에 λ‹€λ₯Έ 값이 μΆ”κ°€λœ 것을 확인할 수 μžˆλ‹€.

 

λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄μ˜ μ€‘μš”ν¬μΈνŠΈλŠ” ν”„λ‘μ‹œ νŒ¨ν„΄μ˜ μ€‘μš” ν¬μΈνŠΈμ— 'λ°˜ν™˜κ°’μ— λ³€ν™”λ₯Ό 쀄 수 μžˆλ‹€'λŠ” 점이닀.

μ‹±κΈ€ν„΄ νŒ¨ν„΄ (Singleton Pattern)

μ‹±κΈ€ν„΄ νŒ¨ν„΄μ΄λž€ μΈμŠ€ν„΄μŠ€λ₯Ό ν•˜λ‚˜λ§Œ λ§Œλ“€μ–΄ μ‚¬μš©ν•˜κΈ° μœ„ν•œ νŒ¨ν„΄

 

'컀λ„₯μ…˜ ν’€', 'μŠ€λ ˆλ“œ ν’€', 'λ””λ°”μ΄μŠ€ μ„€μ • 객체' λ“±κ³Ό 같은 경우 μΈμŠ€ν„΄μŠ€λ₯Ό μ—¬λŸ¬ 개 λ§Œλ“€κ²Œ 되면

λΆˆν•„μš”ν•œ μžμ›μ„ μ‚¬μš©ν•˜κ²Œ 되고, ν”„λ‘œκ·Έλž¨μ΄ μ˜ˆμƒμΉ˜ λͺ»ν•œ κ²°κ³Όλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

 

μ‹±κΈ€ν„΄ νŒ¨ν„΄μ„ μ μš©ν•˜λ©΄ 두 개의 객체가 μ‘΄μž¬ν•  수 μ—†μœΌλ―€λ‘œ

1. 객체 생성을 μœ„ν•œ new에 μ œμ•½μ„ κ±Έμ–΄μ•Ό ν•˜κ³ 

2. λ§Œλ“€μ–΄μ§„ 단일 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” λ©”μ„œλ“œκ°€ ν•„μš”ν•˜λ‹€.

 

  • newλ₯Ό μ‹€ν–‰ν•  수 없도둝 μƒμ„±μžμ— private μ ‘κ·Ό μ œμ–΄μž μ„€μ •
  • μœ μΌν•œ 단일 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” "정적 λ©”μ„œλ“œ" ν•„μš”
  • μœ μΌν•œ 단일 객체λ₯Ό μ°Έμ‘°ν•  "정적 μ°Έμ‘° λ³€μˆ˜" ν•„μš”

싱클턴 νŒ¨ν„΄ μ μš©μ„ μœ„ν•œ 클래슀 ꡬ성

public class Singleton {
	static Singleton singletonObject; // 정적 μ°Έμ‘° λ³€μˆ˜

	private Singleton() {
	}; // private μƒμ„±μž

	// 객체 λ°˜ν™˜ 정적 λ©”μ„œλ“œ
	public static Singleton getInstance() {
		if (singletonObject == null) {
			singletonObject = new Singleton();
		}

		return singletonObject;
	}
}

μƒμ„±μžλ₯Ό μ‚¬μš©ν•˜μ§€ λͺ»ν•˜λ„둝 μ„€μ •ν–ˆκ³  "정적 λ©”μ„œλ“œ"λ₯Ό μ‹€ν–‰ν•΄ 정적 μ°Έμ‘° λ³€μˆ˜μ— 객체가 ν• λ‹Ήλ˜μ–΄ μžˆμ§€μ•ŠμœΌλ©΄ ν• λ‹Ήν•΄μ„œ λ°˜ν™˜ν•˜κ³  ν• λ‹Ήλ˜μ–΄ 있으면 μ°Έμ‘° λ³€μˆ˜λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ λ§Œλ“€μ—ˆλ‹€.

 

ν…ŒμŠ€νŠΈ μ½”λ“œ

public class Client {
	public static void main(String[] args) {
		// private μƒμ„±μžμž„μœΌλ‘œ new ν•  수 μ—†λ‹€.
		// Singleton s = new Singleton();

		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		Singleton s3 = Singleton.getInstance();

		System.out.println(s1);
		System.out.println(s2);
		System.out.println(s3);

		s1 = null;
		s2 = null;
		s3 = null;
	}
}

μœ„ ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” s1, s2, s3 λͺ¨λ‘ 같은 μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•˜κ²Œ λœλ‹€.

 

Tλ©”λͺ¨λ¦¬ ꡬ성

4개의 μ°Έμ‘° λ³€μˆ˜κ°€ λͺ¨λ‘ ν•˜λ‚˜μ˜ 단일 객체λ₯Ό μ°Έμ‘°ν•˜λŠ” 것을 확인할 수 μžˆλ‹€.'

μ‹±κΈ€ν„΄ νŒ¨ν„΄μ˜ μ€‘μš” 포인트

  • private μƒμ„±μžλ₯Ό κ°–λŠ”λ‹€.
  • 단일 객체 μ°Έμ‘° λ³€μˆ˜λ₯Ό "정적 속성"으둜 κ°–λŠ”λ‹€.
  • 단일 객체 μ°Έμ‘° λ³€μˆ˜κ°€ μ°Έμ‘°ν•˜λŠ” "단일 객체"λ₯Ό λ°˜ν™˜ν•˜λŠ” getInstance() 정적 λ©”μ„œλ“œλ₯Ό κ°–λŠ”λ‹€.
  • 단일 κ°μ²΄λŠ” μ“°κΈ° κ°€λŠ₯ν•œ 속성을 갖지 μ•ŠλŠ” 것이 정석이닀. (읽기 μ „μš©μ€ κ°€λŠ₯)

ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄

μƒμœ„ 클래슀의 견본 λ©”μ„œλ“œμ—μ„œ ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ”©ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” νŒ¨ν„΄

κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œλŠ” μƒμœ„ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„.

ν•˜μœ„ν΄λž˜μŠ€λ§ˆλ‹€ λ‹¬λΌμ§€λŠ” 것은 μΆ”μƒν΄λž˜μŠ€λ‘œ κ΅¬ν˜„ κ°•μ œν™”.

ν•˜μœ„ν΄λž˜μŠ€λ§ˆλ‹€ λ‹¬λΌμ§ˆ μˆ˜λ„ μžˆλŠ” 것은 μ˜€λ²„λΌμ΄λ“œ κ°€λŠ₯ν•œ ν›… λ©”μ„œλ“œλ‘œ λ§Œλ“¬.

 

κ°œμ™€ 고양이λ₯Ό λ†€μ•„μ£ΌλŠ” playWithOwnerλΌλŠ” λ©”μ„œλ“œκ°€ μžˆμ„ λ•Œ ν•˜λ‚˜μ˜ μƒμœ„ 클래슀둜 μ‹€μ œ μΈμŠ€ν„΄μŠ€μ— λ§žλŠ” λ©”μ„œλ“œλ‘œ μ‹€ν–‰ν•˜κ³  싢을 λ•Œ μ‚¬μš©ν•œλ‹€.

Animal 좔상 클래슀

public abstract class Animal {
	// ν…œν”Œλ¦Ώ λ©”μ„œλ“œ
	public void playWithOwner() {
		System.out.println("κ·€μ—Όλ‘₯이 이리온...");
		play();
		runSomething();
		System.out.println("μž˜ν–ˆμ–΄");
	}

	// 좔상 λ©”μ„œλ“œ
	abstract void play();

	// Hook(갈고리) λ©”μ„œλ“œ
	void runSomething() {
		System.out.println("꼬리 μ‚΄λž‘ μ‚΄λž‘~");
	}
}

μƒμœ„ν΄λž˜μŠ€μ—μ„œ ν…œν”Œλ¦Ώμ„ μ œκ³΅ν•˜λŠ” playWithOwner() ν…œν”Œλ¦Ώ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

그리고 ν…œν”Œλ¦Ώ λ©”μ„œλ“œ μ•ˆμ— μžˆλŠ” play() 좔상 λ©”μ„œλ“œμ™€ runSomething() λ©”μ„œλ“œκ°€ μžˆλ‹€.

 

-> 좔상 λ©”μ„œλ“œ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ κ°•μ œν•¨

-> Hook λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ“œ 자유

 

이 λ•Œ ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ˜ κ΅¬μ„±μš”μ†Œλ₯Ό μ•Œμ•„ 보자.

  • ν…œν”Œλ¦Ώ λ©”μ„œλ“œ : 곡톡 둜직 μˆ˜ν–‰, 둜직 μˆ˜ν–‰ 쀑 μΆ”μƒλ©”μ„œλ“œ/ν›… λ©”μ„œλ“œ 호좜
  • ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ—μ„œ ν˜ΈμΆœν•˜λŠ” μΆ”μƒλ©”μ„œλ“œ -> λ°˜λ“œμ‹œ ν•˜μœ„ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ”© ν•΄μ•Όν•œλ‹€.
  • ν…œν”Œλ¦Ώ λ©”μ„œλ“œμ—μ„œ ν˜ΈμΆœν•˜λŠ” ν›… λ©”μ„œλ“œ -> ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ„ νƒμ μœΌλ‘œ μ˜€λ²„λΌμ΄λ”© ν•œλ‹€.

ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ˜ 클래슀 λ‹€μ΄μ–΄κ·Έλž¨

νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ (Factory Method Pattern)

μ˜€λ²„λΌμ΄λ“œ 된 λ©”μ„œλ“œκ°€ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” νŒ¨ν„΄

νŒ©ν„°λ¦¬ λ©”μ„œλ“œλŠ” 객체λ₯Ό 생성 λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œλ₯Ό λ§ν•œλ‹€.

 

νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ€ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•΄μ„œ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

 

좔상 νŒ©ν† λ¦¬ λ©”μ„œλ“œ

public abstract class Animal {
	// 좔상 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ
	abstract AnimalToy getToy();
}

 

좔상 νŒ©ν† λ¦¬ λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©

public class Dog extends Animal {
	// 좔상 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©
	@Override
	AnimalToy getToy() {
		return new DogToy();
	}
}

 

메인 λ©”μ„œλ“œ

public class Driver {
	public static void main(String[] args) {
		// νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό λ³΄μœ ν•œ 객체듀 생성
		Animal bolt = new Dog();
		Animal kitty = new Cat();

		// νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•˜λŠ” 객체듀
		AnimalToy boltBall = bolt.getToy();
		AnimalToy kittyTower = kitty.getToy();

		// νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•œ 객체듀을 μ‚¬μš©
		boltBall.identify();
		kittyTower.identify();
	}
}

 

νŒ©ν„°λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ€..

"μ˜€λ²„λΌμ΄λ“œλœ λ©”μ„œλ“œκ°€ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” νŒ¨ν„΄"

μ „λž΅ νŒ¨ν„΄ (Strategy Pattern)

μ „λž΅ νŒ¨ν„΄ κ΅¬μ„±μš”μ†Œ 3가지

  • μ „λž΅ λ©”μ„œλ“œλ₯Ό 가진 μ „λž΅ 객체
  • μ „λž΅ 객체λ₯Ό μ‚¬μš©ν•˜λŠ” μ»¨ν…μŠ€νŠΈ (μ „λž΅ 객체의 μ‚¬μš©μž/μ†ŒλΉ„μž)
  • μ „λž΅ 객체λ₯Ό 생성해 μ»¨ν…ŒμŠ€νŠΈμ— μ£Όμž…ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈ (μ „λž΅ 객체의 κ³΅κΈ‰μž)

μ „λž΅ 객체의 κ°œλ…λ„

μ „λž΅ μΈν„°νŽ˜μ΄μŠ€

public interface Strategy {
	public abstract void runStrategy();
}

μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„

public class StrategyGun implements Strategy {
	@Override
	public void runStrategy() {
		System.out.println("탕, 타당, 타닀당");
	}
}

public class StrategySword implements Strategy {
	@Override
	public void runStrategy() {
		System.out.println("μ±™.. μ±„μŸμ±™ μ±™μ±™");
	}
}

μ „λž΅μ„ μ‚¬μš©ν•˜λŠ” μ»¨ν…μŠ€νŠΈ

public class Soldier {
	void runContext(Strategy strategy) {
		System.out.println("μ „νˆ¬ μ‹œμž‘");
		strategy.runStrategy();
		System.out.println("μ „νˆ¬ μ’…λ£Œ");
	}
}

μ „λž΅ νŒ¨ν„΄μ˜ ν΄λΌμ΄μ–ΈνŠΈ

public class Client {
	public static void main(String[] args) {
		Strategy strategy = null;
		Soldier rambo = new Soldier();

		// 총을 λžŒλ³΄μ—κ²Œ μ „λ‹¬ν•΄μ„œ μ „νˆ¬λ₯Ό μˆ˜ν–‰ν•˜κ²Œ ν•œλ‹€.
		strategy = new StrategyGun();
		rambo.runContext(strategy);

		System.out.println();

		// 검을 λžŒλ³΄μ—κ²Œ μ „λ‹¬ν•΄μ„œ μ „νˆ¬λ₯Ό μˆ˜ν–‰ν•˜κ²Œ ν•œλ‹€.
		strategy = new StrategySword();
		rambo.runContext(strategy);

		System.out.println();

		// ν™œμ„ λžŒλ³΄μ—κ²Œ μ „λ‹¬ν•΄μ„œ μ „νˆ¬λ₯Ό μˆ˜ν–‰ν•˜κ²Œ ν•œλ‹€.
		strategy = new StrategyBow();
		rambo.runContext(strategy);
	}
}

 

ν΄λΌμ΄μ–ΈνŠΈλŠ” μ „λž΅μ„ λ‹€μ–‘ν•˜κ²Œ λ³€κ²½ν•˜λ©΄μ„œ μ»¨ν…μŠ€νŠΈλ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€.

 

μ „λž΅ νŒ¨ν„΄μ„ ν•œ λ¬Έμž₯으둜 μš”μ•½ν•˜λ©΄..

ν΄λΌμ΄μ–ΈνŠΈκ°€ μ „λž΅μ„ 생성해 μ „λž΅μ„ μ‹€ν–‰ν•  μ»¨ν…μŠ€νŠΈμ— μ£Όμž…ν•˜λŠ” νŒ¨ν„΄

μ „λž΅ νŒ¨ν„΄μ—λŠ” OCP, DIPκ°€ μ μš©λœλ‹€.

 

ν…œν”Œλ¦Ώ 콜백 νŒ¨ν„΄ (Template Callback Pattern)

ν…œν”Œλ¦Ώ 콜백 νŒ¨ν„΄μ€ μ „λž΅ νŒ¨ν„΄μ˜ λ³€ν˜•μœΌλ‘œ, μŠ€ν”„λ§ 3λŒ€ ν”„λ‘œκ·Έλž˜λ° λͺ¨λΈ 쀑 ν•˜λ‚˜μΈ DIμ—μ„œ μ‚¬μš©ν•˜λŠ” νŠΉλ³„ν•œ ν˜•νƒœμ˜ μ „λž΅ νŒ¨ν„΄μ΄λ‹€.

 

μ „λž΅νŒ¨ν„΄κ³Ό λͺ¨λ“  것이 λ™μΌν•œλ° μ „λž΅μ„ 읡λͺ… λ‚΄λΆ€ 클래슀둜 μ •μ˜ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

λ”°λΌμ„œ, μ „λž΅νŒ¨ν„΄μ—μ„œ μ‚¬μš©ν–ˆλ˜ StrategyGun, StrategySwordλŠ” ν•„μš”κ°€ μ—†λ‹€.

public class Client {
	public static void main(String[] args) {
		Soldier rambo = new Soldier();

		rambo.runContext(new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println("총! μ΄μ΄ˆμ’…μ΄ 총! 총!");
			}
		});

		System.out.println();

		rambo.runContext(new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println("μΉΌ! μΉ΄κ°€κ°ˆ μΉΌ! μΉΌ!");
			}
		});

		System.out.println();

		rambo.runContext(new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println("도끼! 독독..도도독 독끼!");
			}
		});
	}
}

읡λͺ… λ‚΄λΆ€ 클래슀λ₯Ό μ‚¬μš©ν•΄μ„œ μ˜€λ²„λΌμ΄λ“œν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€. (λ”°λ‘œ 클래슀λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•¨ [콜백])

 

μœ„ μ½”λ“œλŠ” 쀑볡 μ½”λ“œκ°€ λ°œμƒν•œλ‹€...즉, λ¦¬νŒ©ν„°λ§μ΄ κ°€λŠ₯ν•˜λ‹€.

λ¦¬νŒ©ν„°λ§ 해보기

public class Soldier {
	void runContext(String weaponSound) {
		System.out.println("μ „νˆ¬ μ‹œμž‘");
		executeWeapon(weaponSound).runStrategy();
		System.out.println("μ „νˆ¬ μ’…λ£Œ");
	}

	private Strategy executeWeapon(final String weaponSound) {
		return new Strategy() {
			@Override
			public void runStrategy() {
				System.out.println(weaponSound);
			}
		};
	}
}

ν΄λΌμ΄μ–ΈνŠΈ

public class Client {
	public static void main(String[] args) {
		Soldier rambo = new Soldier();
		
		rambo.runContext("총! μ΄μ΄ˆμ’…μ΄ 총! 총!");
		
		System.out.println();
		
		rambo.runContext("μΉΌ! μΉ΄κ°€κ°ˆ μΉΌ! μΉΌ!");
		
		System.out.println();
		
		rambo.runContext("도끼! 독독..도도독 독끼!");
	}
}

μ€‘λ³΅λ˜λŠ” μ „λž΅μ„ μƒμ„±ν•˜λŠ” μ½”λ“œκ°€ μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€λ‘œ λ“€μ–΄μ™”λ‹€. (μ€‘λ³΅λ˜λŠ” 뢀뢄을 μ»¨ν…μŠ€νŠΈλ‘œ 이관)

 

μŠ€ν”„λ§μ€ 이런 ν˜•μ‹μœΌλ‘œ λ¦¬νŒ©ν„°λ§λœ ν…œν”Œλ¦Ώ 콜백 νŒ¨ν„΄μ„ DI에 적극 ν™œμš©ν•˜κ³  μžˆλ‹€.

 

** μš”μ•½ **

"μ „λž΅μ„ 읡λͺ… λ‚΄λΆ€ 클래슀둜 κ΅¬ν˜„ν•œ μ „λž΅ νŒ¨ν„΄"

OCP, DIP 적용된 섀계 νŒ¨ν„΄