12. Design Patterns
Learning Goals
- Design pattern์ ๋๊ธฐ ์ดํด (์๋ฃจ์ ์ template๋ก์)
- ๋ค์ํ design pattern ์ ํ ํ์ต
- Design pattern ์ฌ์ฉ ์์ ๋ ผ์
- ๋ฌธ์ ํด๊ฒฐ์ ์ํ ์ ์ ํ design pattern ์ ์ฉ
Design Challenges
- ์ฌ์ฌ์ฉ์ ์ํ software ์ค๊ณ์ ์ด๋ ค์.
- ์ฐพ์์ผ ํ ๊ฒ๋ค
- ์ฐ์ํ ๋ฌธ์ ๋ถํด ๋ฐ ์ ์ ํ software
- ์ ์ฐ์ฑ, ๋ชจ๋์ฑ, ๋ช ๋ฃ์ฑ์ ๊ฐ์ถ design
- ์ํ ์ฐฉ์ค๋ฅผ ํตํด ๋์์ธ ๋์ถ
- ์ฑ๊ณต์ ์ธ ๋์์ธ ์กด์ฌ
- ๋ ๋์์ธ์ด ๊ฑฐ์ ๋์ผํ์ง ์์
- ์ผ๋ถ ๋ฐ๋ณต์ ์ธ ํน์ฑ ์กด์ฌ
- ๋์์ธ์ described, ์ฝ๋ํ, ํ์คํํ ์ ์๋๊ฐ?
- ์ํ์ฐฉ์ค ๋จ๊ณ ๋จ์ถ
- "๋ ๋์" software๋ฅผ ๋ ๋นจ๋ฆฌ ์์ฐ
Design Principles
Application์์ ๋ณํํ๋ ๋ถ๋ถ์ ์๋ณํ์ฌ ๋ณํ์ง ์๋ ๋ถ๋ถ๊ณผ ๋ถ๋ฆฌImpleementation์ด ์๋ interface์ ๋ง์ถฐ programInheritance๋ณด๋ค composition์ ์ ํธ์ํธ์์ฉํ๋ object ๊ฐ์ loosely coupled design ์ถ๊ตฌClasses๋ extension์ ๋ํด์ ์ด๋ ค ์์ด์ผ ํ๋, modification์ ๋ํด์๋ ๋ซํ ์์ด์ผ ํจ.
Design Patterns
"๊ฐ ํจํด์ ์ฐ๋ฆฌ ํ๊ฒฝ์์ ๋ฐ๋ณต์ ์ผ๋ก ๋ฐ์ํ๋ ๋ฌธ์ ์ ๊ทธ ๋ฌธ์ ์ ๋ํ ํต์ฌ ํด๊ฒฐ์ฑ ์ ์ค๋ช ํจ. ์ด ํด๊ฒฐ์ฑ ์ ๋ ๋ฒ ๋ค์ ๋๊ฐ์ ๋ฐฉ์์ผ๋ก ์ํํ์ง ์๊ณ ๋ ๋ฐฑ๋ง ๋ฒ ์ด์ ์ฌ์ฉ ๊ฐ๋ฅ" (Christopher Alexander, 1977)
- ๊ฑด๋ฌผ๊ณผ ๋ง์์ pattern ์ค๋ช ์์ ์ ๋
- ์ํํธ์จ์ด ๊ณตํ์์, design ํจํด์ ๋ฒฝ๊ณผ ๋ฌธ์ด ์๋ object์ interface ๊ด์
- ์ํธ์์ฉํ๋ object ์งํฉ์ด ํน์ ์์ ์ ์ํํ๊ฑฐ๋ ํน์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ์ํด ํ์ ํ๋ ๋ฐฉ์
Design Patterns Everywhere!
History of Patterns
- "Pattern"์ ๊ฐ๋ ์ 1977๋ Christopher Alexander์ A Pattern Language (2543๊ฐ patterns)์์ ์ฒ์ ๋ฑ์ฅ
- 1990๋ Gang of Four or "GoF"(Gamma, Helm, Johnson, Vlissides) ๊ทธ๋ฃน์ด design pattern ์นดํ๋ก๊ทธ ํธ์ฐฌ
- 1995๋ ์ฑ Design Patterns: Elements of Reusable Object-Oriented Software๋ ์ด ๋ถ์ผ์ ๊ณ ์
Benefits of Using Patterns
- ํจํด์ ๊ณตํต ๋์์ธ ์ดํ
- ์์ง๋์ด๊ฐ ๋ฌธ์ ๋ฅผ ์ถ์ํํ๊ณ ๊ตฌํ๊ณผ ๋ถ๋ฆฌํ์ฌ ๋ ผ์ ๊ฐ๋ฅ
- ๋ฌธํ ๊ตฌํ; ๋๋ฉ์ธ ํนํ ํจํด์ ๋์์ธ ์๋ ํฅ์
- ํจํด์ ๋์์ธ ์ ๋ฌธ์ฑ์ ํฌ์ฐฉํ๊ณ ์ ๋ฌ
- ๋์์ธ ์ฌ์ฌ์ฉ ์ด์ง ๋ฐ ์ค์ ๋ฐฉ์ง
- ๋ฌธ์ํ ๊ฐ์ (๋ ์ ์ ์ ํ์) ๋ฐ ์ดํด๋ ํฅ์ (ํจํด์ ํ ๋ฒ ์ ์ค๋ช ๋จ)
Architecture vs. Design Patterns
- Architecture
- Application ๊ตฌ์กฐํ๋ฅผ ์ํ ์์ ์์ค์ framework
- "RPC ๊ธฐ๋ฐ client-server"
- "์ถ์ํ ๋ ์ด์ด๋ง"
- "CORBA ๊ธฐ๋ฐ ๋ถ์ฐ ๊ฐ์ฒด ์งํฅ system"
- Application ๊ตฌ์กฐํ๋ฅผ ์ํ ์์ ์์ค์ framework
- ๊ณ์ฐ component ๋ฐ ์ํธ์์ฉ ๊ด์ ์์ system ์ ์
- Design Patterns
- Architecture๋ณด๋ค ๋ฎ์ ์์ค (๋๋๋ก micro-architecture)
- Application ๋ด ํ์ ๋ฌธ์ ํด๊ฒฐ์ ์ํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํ์
- Subsystem X๋ฅผ Subsystem Y์์ ์ด๋ป๊ฒ ๋ถ๋ฆฌ(decouple)ํ ๊น?
- Why Design Patterns?
- ๋์ ์ถ์ํ ์์ค์์ ๊ฐ์ฒด ์งํฅ ์ฌ์ฌ์ฉ ์ง์
- ๊ฐ์ฒด ์งํฅ ๊ตฌํ์ ์๋ดํ๊ณ ์ ์ฝํ๋ "framework" ์ ๊ณต
4 Essential Elements of Design Patterns
- Name: Pattern ์๋ณ
- Problem: ๋ฌธ์ ๋ฐ context ๊ด์ ์์ pattern ์ ์ฉ ์์ ๊ธฐ์
- Solution: Design ๊ตฌ์ฑ ์์, ๊ด๊ณ, ์ฑ ์, ํ์ ๊ธฐ์
- Consequences: Pattern ์ ์ฉ ๊ฒฐ๊ณผ ๋ฐ trade-off
How to Describe Design Patterns more fully
๋๋ฃ ๊ฐ๋ฐ์๊ฐ pattern์ ํ๊ฐ, ์ ํ, ํ์ฉํ ์ ์๋๋ก ์ ๋ณด ์ ๋ฌ์ด ์ค์
- Design pattern์ ์ํ ํ์
- Pattern Name and Classification
- Intent
- Also Known As
- Motivation
- Applicability
- Structure
- Participants
- Collaborations
- Consequences
- Implementation
- Sample Code
- Known Uses
- Related Patterns
Organizing Design Patterns
- By Purpose (pattern์ ์ญํ ๋ฐ์)
- Creational Patterns
- Structural Patterns
- Behavioral Patterns
- By Scope: Pattern์ด ์ฃผ๋ก ์ด๋์ ์ ์ฉ๋๋์ง ๊ตฌ์ฒดํ
- Classes
- Objects
Design Patterns Space

Creational Patterns
"System์ด object ์์ฑ ๋ฐฉ์๊ณผ ๋ ๋ฆฝ์ ์ด๋๋ก ๋ง๋ค์ด๋ผ."
- ์ผ๋ฐ constructor๊ฐ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ
- Object ์์ฑ ๋ฐฉ์/์์ ์ ์ด
- ์ธ์ด ํ๊ณ ๊ทน๋ณต (์: keyword/default args ๋ถ์ฌ)
- Polymorphic type ์จ๊น
Named Constructor (Idiom)
- Creational pattern์์ ์ฌ์ฉ๋๋ ๊ธฐ๋ฒ
class Llama {
public
static Llama create_llama(String name) {
return new Llama(name);
}
private: // Making ctor private depends on our needs
Llama(String name_in){ name = name_in; }
String name;
};
Scenario: Polymorphic Objects
- Problem: Client์๊ฒ type์ ๋ ธ์ถํ์ง ์๊ณ polymorphic object๋ฅผ ์์ฑ ๋ฐ ์ฌ์ฉ
- Solution: ์ํ๋ type์ object๋ฅผ ์์ฑํ๋, base class์ object๋ฅผ ๋ฐํํ๋ ํจ์ ์์ฑ
Factory Pattern (Function)
- String์ด factory์ ์์ฑํ type ์ ๋ฌ
Llama llama_factory(String name, String type) {
if (type == "ninja_llama") {
return new NinjaLlama(name);
}
if (type == "whooping_llama") {
return new WhoopingLlama(name);
}
...
}
Llama steve = llama_factory("Steve", "ninja_llama");
Factory Pattern (Class)
- Client๊ฐ (์๋ง๋) static method๋ฅผ ํธ์ถํ์ฌ ์ฌ๋ฐ๋ฅธ type ์์ฑ
class LlamaFactory {
public
static Llama make_ninja_llama(string name) {
return new NinjaLlama(name);
}
static Llama make_whooping_llama(string name) {
return new WhoopingLlama(name);
}
};
Llama steve =
LlamaFactory.make_ninja_llama("Steve");
Scenario: Difficulty-Based Enemies
- Polymorphic Enemy class ๊ณ์ธต ๊ตฌ์กฐ์ ์ปดํจํฐ ๊ฒ์ ๊ตฌํ ์ค. ์ ํ๋ ๋์ด๋์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฒ์ ์ enemy ์์ฑ์ ์ํจ
- "Normal" ๋์ด๋: Regular goomba
- "Hard" ๋์ด๋: Spiked goomba
- Bad Solution: Enemy ์์ฑ ์์ ๋ง๋ค ๋์ด๋ ํ์ธ
// !! DON'T DO THIS !!
Enemy* goomby = nullptr;
if (difficulty == "normal") {
goomby = new Goomba();
}
else if (difficulty == "hard") {
goomby = new SpikedGoomba();
}
Solution: Abstract Factory
โโโโโโโโโโโโโโโโโโโโโโ
โAbstractEnemyFactoryโ
โ- create_goomba() โ
โโโโโโโโโฒโโโโโฒโโโโโโโโ
โ โ
โ โ
โโโโโโโโโโโโโโโโโโโดโ โโดโโโโโโโโโโโโโโโโโ
โNormalEnemyFactoryโ โHardEnemyFactory โ
โ- create_goomba() โ โ- create_goomba()โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
// Only have to do this once!
AbstractEnemyFactory factory = null;
if (difficulty == โnormalโ) {
factory = new NormalEnemyfactory();
}
else if (difficulty == โhardโ) {
factory = new HardEnemyFactory();
}
...
Enemy goomby = factory.create_goomba();
โโโโโโโโโ
โ Enemy โ
โโโโโฒโโโโ
โ
โโโโโดโโโโ
โGoomba โ
โโโโโฒโโโโ
โ
โโโโโโโโดโโโโโโโ
โSpiked Goombaโ
โโโโโโโโโโโโโโโ
Scenario: Global Application State
- Globalํ๊ฒ access ๊ฐ๋ฅํ application state ํ์. Data ์ ๊ทผ ๋ฐ ๊ฐฑ์ ์ ์ด ํ์
- Bad solution: ์์ global ๋ณ์ (plz no)
- Less bad solution: ๋ชจ๋ state`๋ฅผ class์ ๋ฃ๊ณ global instance ๋ณด์
Aside: When is Global State OK?
- ๋ชจ๋ ๊ณณ์์ access ํ์, parameter ์ ๋ฌ์ด ์ฝ๋๋ฅผ ๊ณผ๋ํ๊ฒ ๋ณต์กํ๊ฒ ๋ง๋ฆ
- Parameter ์ ๋ฌ ์ค์ด๋ ค๊ณ global ๋ณ์ ์ฌ์ฉ์ BAD
- Program ์ธ๋ถ์ ์ ์ฅ๋ state (database, web API ๋ฑ)
๊ฒฝ๊ณ
Global ๋ณ์๋ ์ฌ์ ํ ๋์จ!
Singleton Pattern
- "Class๊ฐ ๋จ ํ๋์ instance`๋ง ๊ฐ๋๋ก ๋ณด์ฅํ๊ณ , ์ด์ ๋ํ global ์ ๊ทผ ์ง์ ์ ๊ณต"
public
- static get_instance() // named ctor
private
- static instance // the one instance
- Singleton() // ctor
Singleton (๊ตฌํ)
class Singleton {
public static Singleton get_instance() {
if (Singleton.instance == null) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
private static Singleton instance = null;
private Singleton() {
spams = 42;
System.out.println("Singleton created");
}
// Our global state
private int spams;
public int num_spams() {
return spams;
}
public void add_spam() {
spams += 1;
}
}
Using the Singleton
- Exercise: ์ด code์ ์ถ๋ ฅ์?
public
- static get_instance() // named ctor
- num_spams()
- add_spam() // adds 1 to num_spams
private
- static instance // the one instance
- Singleton() // ctor, prints message
- spams
class Main {
public static void main(String[] args) {
int spams = Singleton.get_instance().num_spams();
System.out.println(spams);
Singleton.get_instance().add_spam();
spams = Singleton.get_instance().num_spams();
System.out.println(spams);
}
}
Using the Singleton (Solution)
- Exercise: ์ด code์ ์ถ๋ ฅ์?
class Main {
public static void main(String[] args) {
int spams = Singleton.get_instance().num_spams();
System.out.println(spams);
Singleton.get_instance().add_spam();
spams = Singleton.get_instance().num_spams();
System.out.println(spams);
}
}
- Output
Singleton created
42
43
Singleton.get_instance()
- ํ์ดํ์ด ๋ง์. ๋ง์ฝ ์ด๋ ๊ฒ ํ๋ค๋ฉด?
Singleton s = Singleton.get_instance();
System.out.println(s.num_spams())
- ๊ทธ๋์, ์ข์๊ฐ? ์ข์ง ์์๊ฐ?
Singleton.get_instance()๊ฐ ๋งค๋ฒ ๋์ผํ object๋ฅผ ๋ฐํํ๋ค๋ ๋ณด์ฅ ์์
Singleton: Design Scenario
- ์นด๋ ๊ฒ์ Euchre ์ปดํจํฐ ๋ฒ์ ๊ตฌํ ์ค. Game class๊ฐ ๊ฒ์ state ์ ์ฅ
- Application ์์ ์, Euchre ํ ๊ฒ์ ํ๋ ์ด ํ ์ข ๋ฃ
- Game
์ singleton์ผ๋ก ๋ง๋ค์ด์ผ ํ๋๊ฐ?
Make Game a Singleton?
- ์ฐฌ์ฑ
- Application์ Game instance๊ฐ ํ๋๋ง ์กด์ฌ
- ๋ฐ๋
- Game instance๊ฐ ์ฐ์ฐํ ํ๋์ผ ๋ฟ, ํ๋๋ง ์์ด์ผ ํ๋ค๋ ์๊ตฌ์ฌํญ ์์
- Singleton ํจํด์ application ์๊ตฌ์ฌํญ์ด ๋จ ํ๋์ instance ์กด์ฌ๋ฅผ ๋ช ์ํ ๋๋ง ์ฌ์ฉ
- Singleton ํจํด์ ๋ชจ๋ ๊ฒ์ global๋ก ๋ง๋ค๊ธฐ ์ํ ๋ณ๋ช ์ด ์๋
Structural Patterns
- ๊ธฐ์กด class interface๋ก๋ถํฐ ์๋ก์ด class interface ๊ตฌ์ถ
- ๊ตฌํ ์ธ๋ถ์ฌํญ ์จ๊น
- ๋ ๊น๋ํ๊ณ ํนํ๋ interface ์ ๊ณต
- ์ต์ํ๊ฐ?
Adapter Pattern
- "Class์ interface๋ฅผ client๊ฐ ๊ธฐ๋ํ๋ ๋ค๋ฅธ interface๋ก ๋ณํ"
- "Gang of Four" Design Patterns book

- Problem: ํ์ํ ๊ธฐ๋ฅ์ ์์ง๋ง ์ํ๋ ๋ฐฉ์์ด ์๋ object ๋ณด์
- ์ฌ์ฉํ๊ธฐ ๋ฒ๊ฑฐ๋กญ๊ณ /๋ถํธํจ. Bug ๋ฐ์ ์ฌ์
- Example
- Iterator๋ ์์ง๋ง collection์ ์์
- For-each loop ์คํ ์ํจ. Iterator๋ก๋ ๋ถ๊ฐ๋ฅ, Iterable ํ์
public void printAll(Iterator itr) {
// error: must implement Iterable
for (String s : itr) {
System.out.println(s);
}
}
Adapter in Action
- Solution: ์ ๊ณต๋ ๊ธฐ๋ฅ๊ณผ ์ํ๋ ๊ธฐ๋ฅ ์ฌ์ด๋ฅผ ์ฐ๊ฒฐํ๋ adapter object ์์ฑ
public class IterableAdapter implements Iterable {
private Iterator iterator;
public IterableAdapter(Iterator itr) {
this.iterator = itr;
}
public Iterator iterator() {
return iterator;
}
}
...
public void printAll(Iterator itr) {
IterableAdapter adapter = new IterableAdapter(itr);
for (String s : adapter) { ... } // works
}
Adapter Pattern (More Examples)
- C++
fstream์ด๊ธฐ ๊ตฌํ - C FILE macro๋ฅผ ์ํ Adapter
Other Structural Patterns
- Composite: Client๊ฐ ๊ฐ๋ณ object์ object ๊ทธ๋ฃน์ ๋์ผํ๊ฒ ์ฒ๋ฆฌ
- ์: PowerPoint์์ object ์ ํ ๋ฐ ์ด๋
- Proxy: "๋ค๋ฅธ object์ ๋ํ ์ ๊ทผ ์ ์ด๋ฅผ ์ํด surrogate(๋๋ฆฌ์) ๋๋ placeholder ์ ๊ณต"
- ์:
std::vector::reference
- ์:
Composite Pattern
- Example: ๊ทธ๋ฆฌ๊ธฐ ํธ์ง๊ธฐ ๊ฐ์ ๊ทธ๋ํฝ application
- ๋จ์ component๋ก ๋ณต์กํ ๋ค์ด์ด๊ทธ๋จ ๊ตฌ์ถ

Behavioral Patterns
- "Behavioral ํจํด์ algorithm ๋ฐ object ๊ฐ ์ฑ ์ ํ ๋น๊ณผ ๊ด๋ จ"
- ์ด๋ฏธ ๋ณธ Behavioral pattern: Iterator pattern
- ๊ตฌํ ๋ฐฉ์๊ณผ ๋ฌด๊ดํ๊ฒ container ์ํ๋ฅผ ์ํ ํต์ผ๋ interface
Scenario: โLock-onโ in Action-Adventure Game
"ํ๋ ์ด์ด ์บ๋ฆญํฐ๊ฐ ์ ์๊ฒ โlock-onโ(์ด๋๊ณผ ์๊ด์์ด ์ ์ ํฅํด ์ผ๊ตด์ ๋๋ฆผ)ํ ์ ์๋ ์ปดํจํฐ ๊ฒ์์ ๊ตฌํ ์ค์ด๋ค. lock-on๋ ์ ์ด ์ฐ๋ฌ์ง๋ฉด ์บ๋ฆญํฐ๋ ํด๋น ์ ์ ๋ ์ด์ ์กฐ์คํ์ง ์์์ผ ํ๋ค."
โLock-onโ: Not-so-good Implementation
- Enemy๊ฐ ์ฐ๋ฌ์ง๋ฉด, player character์
release_lock_on()ํธ์ถ
class Player {
public void
release_lock_on(Enemy enemy) {
if (enemy == locked_on) {
locked_on = null;
}
}
private Enemy locked_on;
}
class Enemy {
// Called when the enemy is defeated
public void on_death() {
// Global accessor for the player
// character
get_player().release_lock_on(this);
}
}
- ์ด ์ ๊ทผ ๋ฐฉ์์ ๋ฌธ์ ์ ์?
- Player`์ Enemy๊ฐ tightly coupled (๊ฐํ๊ฒ ๊ฒฐํฉ)
- ํ๋๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋ค๋ฅธ ํ๋๋ ๋ณ๊ฒฝํด์ผ ํจ
- Player๊ฐ ๋ ์ด์์ด๋ผ๋ฉด?
- Enemy
๋ฅผ ์ฐ๋ฌ๋จ๋ฆด ๋ player์ "score"๋ฅผ ๊ฐฑ์ ํ๊ณ ์ถ๋ค๋ฉด? - Enemy ์ฌ๋ง ์ ์๋ก์ด ์์ ์ถ๊ฐ ์, Enemy class๋ฅผ ์์ ํ๊ณ ์ feature์ couple`ํด์ผ ํจ
Observer Pattern (a.k.a. โPublish-Subscribeโ)
"๊ฐ์ฒด ๊ฐ ์ผ๋๋ค ์ข ์์ฑ์ ์ ์ํ์ฌ, ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ชจ๋ ์ข ์ ๊ฐ์ฒด๊ฐ ์๋์ผ๋ก ํต์ง๋ฐ๊ณ update๋๋๋ก ํ๋ค."

Note: ๊ตฌ๋ /๊ตฌ๋ ์ทจ์๋ ๊ตฌํ์ ๋ฐ๋ผ ์ ์ or ๋น์ ์ ์ผ ์ ์์.
class Subject {
public static void subscribe(Observer observer) {
subscribers.Add(observer);
}
public static void unsubscribe(Observer observer)
{
subscribers.Remove(observer);
}
public static void change_state() {
foreach (Observer observer in subscribers) {
observer.update();
}
}
private static List subscribers
= new List();
}
class Observer {
public void update() {
System.out.println("Received update");
}
}
class MainClass {
public static void Main (string[] args) {
Observer observer1 = new Observer();
Observer observer2 = new Observer();
Subject.subscribe(observer1);
Subject.change_state();
Subject.subscribe(observer2);
Subject.change_state();
Subject.unsubscribe(observer2);
Subject.change_state();
}
}
- Exercise: "Received update"๊ฐ ๋ช ๋ฒ ์ถ๋ ฅ๋๋๊ฐ?
Observer for โLock-onโ Feature

Abstract๋ โํ์ ํด๋์ค๋ ์ด method๋ฅผ ๋ฐ๋์ ์ฌ์ ์ํด์ผ ํ๋คโ๋ ์๋ฏธ
Observer for โLock-onโ Feature (Implementation)
class Enemy {
public static void subscribe(EnemyObserver observer) {
subscribers.Add(observer);
}
public static void unsubscribe(EnemyObserver observer) {
subscribers.Remove(observer);
}
public void on_death() {
foreach (EnemyObserver observer in subscribers) {
observer.update_enemy_defeated(this);
}
}
private static List subscribers
= new List();
}
interface EnemyObserver {
void update_enemy_defeated(Enemy enemy);
}
class Player: EnemyObserver {
public void update_enemy_defeated(Enemy enemy) {
if (enemy == target) {
target = null;
}
}
public void lock_on(Enemy enemy) {
target = enemy;
}
private Enemy target;
}
Observer update_ Functions
- ์ฌ๋ฌ
update_ํจ์๋ ์ธ๋ถํ ์ ์ง - Update์ ๊ด์ฌ ์๋ observer๋ ๋ฌด์ ๊ฐ๋ฅ (๋น ๊ตฌํ)
- Observer๊ฐ data๋ฅผ ๊ฐ์ ธ์ค๊ฒ(pull) ํ๋ ๊ฒ๋ณด๋ค, ์ data๋ฅผ parameter๋ก ์ ๋ฌ(push)ํ๋ ๊ฒ์ด ์ผ๋ฐ์
Scenario: Damage-Dealing in Action Game
"ํ๋ ์ด์ด ์บ๋ฆญํฐ๊ฐ ๋ค์ํ ์ ๊ณผ ์ ํฌ๋ฅผ ๋ฒ์ด๋ ์ปดํจํฐ ๊ฒ์์ ์ ์ ์ค์ด๋ค. ํ๋ ์ด์ด๋ ์ ์ด ๊ณต๊ฒฉ์ ๋ฐ์ผ๋ฉด ํผํด๋ฅผ ์ ๊ณ , ์ฒด๋ ฅ์ด 0์ด ๋๋ฉด ์ฌ๋ง, ํ๋ ์ด์ด๊ฐ ์ฌ๋งํ๋ฉด ๊ฒ์์ด ์ข ๋ฃ๋๋ค. ์ ์ด ์ฌ๋งํ๋ฉด ์์ดํ ์ dropํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ํ๋ ์ด์ด/์ ์ ๋ค๋ก ๋ฐ๋ ค๋๋ฉฐ ์๋ฆฌ๋ฅผ ๋ด๋ฑ๋๋ค."
Damage-Dealing: First Design
- ์ฐธ๊ณ :
receive_hit()์ Actor๊ฐ damage ์ ์ ๋ ํธ์ถ๋จ
class Actor {
public void receive_hit(float damage) {
health -= damage;
}
public float get_health() { return health; }
private float health = 42;
public void apply_knockback() {
System.out.println("Knocked back!");
}
}
class Enemy extends Actor {
public void receive_hit(float damage) {
base.receive_hit(damage);
if (get_health() <= 0) {
System.out.println("Dropped an item");
}
else {
System.out.println("Weah");
apply_knockback();
}
}
}
class Player extends Actor {
public void receive_hit(float damage) {
base.receive_hit(damage);
if (get_health() <= 0) {
System.out.println("Game over");
}
else {
System.out.println("Ow");
apply_knockback();
}
}
}
Template Method Pattern
"โ์๊ณ ๋ฆฌ์ฆ์ ๊ณจ๊ฒฉ์ ํ๋์ ์์ ์ผ๋ก ์ ์ํ๊ณ ์ผ๋ถ ๋จ๊ณ๋ฅผ ํ์ ํด๋์ค๋ก ๋ฏธ๋ฃจ๋ ํจํด์ด๋ค. templete method ํจํด์ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์ผ๋ฉด์ ํ์ ํด๋์ค๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ํน์ ๋จ๊ณ๋ฅผ ์ฌ์ ์ํ ์ ์๋๋ก ํ๋ค.โ"
Damage-Dealing: Template Method

Damage-Dealing: Template Method (Implementation)
Abstract class Actor {
public void receive_hit(float damage) {
health -= damage;
if (get_health() <= 0) {
on_death();
}
else {
play_damaged_sound();
apply_knockback();
}
}
protected void on_death();
protected void play_damaged_sound();
// Other members same as before
}
class Enemy extends Actor {
protected void on_death() {
System.out.println("Dropped an item");
}
protected void play_damaged_sound() {
System.out.println("Weah");
}
}
class Player extends Actor {
protected void on_death() {
System.out.println("Game over");
}
protected void play_damaged_sound() {
System.out.println("Ow");
}
}
Template Method: The โHollywood Principleโ
- ์ฒซ ๊ตฌํ: Derived class๊ฐ Base class์
receive_hit()ํธ์ถ - Template method ๊ตฌํ: Non-virtual base class
receive_hit()์ด derived class method ํธ์ถ
"Donโt call us, weโll call you!"
Exercise: Updating our Algorithm
- Knock back๋ ์ ์๋
TurretEnemy์ถ๊ฐ ๊ฐ์ - ์ enemy type ํฌํจํ๋๋ก design ์์ [UML ๋ค์ด์ด๊ทธ๋จ: Slide 54์ ๋์ผ]

