๐จ 06. ์ปค๋งจ๋ ํจํด
๐ฎ ๋ง๋ฅ IOT ๋ฆฌ๋ชจ์ปจ
์ด ๋ฆฌ๋ชจ์ปจ์ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํ 7๊ฐ์ ์ฌ๋กฏ๊ณผ ๊ฐ ์ฌ๋กฏ์ ํ ๋น๋ ๊ธฐ๋ฅ์ ์ผ๊ณ ๋๋ ON/OFF ์ค์์น๊ฐ ์๋ค. ๊ฐ ์ฌ๋กฏ์ ์๋ก ๋ค๋ฅธ ๊ฐ์ ์ฉ ๊ธฐ๊ธฐ์ ์ฐ๊ฒฐํ ์ ์๊ณ , ์์ ์ทจ์ ๋ฒํผ๋ ์ฅ์ฐฉ๋์ด ์๋ค.
๋ฆฌ๋ชจ์ปจ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด์
- ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํ 7๊ฐ์ ์ฌ๋กฏ์ด ์๋ค. ๊ฐ ์ฌ๋กฏ์ ์ํ๋ ์ ํ์ ์ฐ๊ฒฐํ ๋ค์ ์์ ์๋ ๋ฒํผ์ผ๋ก ์กฐ์ํ ์ ์๋ค.
- 7๊ฐ์ ์ฌ๋กฏ๋ง๋ค โONโ ๋ฒํผ๊ณผ โOFFโ ๋ฒํผ์ด ์๋ค.
- ์ด ๋ ๋ฒํผ์ผ๋ก ๊ฐ๊ฐ์ ์ฌ๋กฏ์ ์ฐ๊ฒฐ๋ ๊ฐ์ ์ ํ์ ์ ์ดํ ์ ์๋ค.
- ๋ง์ง๋ง์ผ๋ก ๋๋ฅธ ๋ฒํผ์ ๋ช ๋ น์ ์ทจ์ํ๋ โUNDOโ ๋ฒํผ๋ ์๋ค.
๐ฎ ํ๋ ฅ ์ ์ฒด ํด๋์ค ์ดํด๋ณด๊ธฐ
CEO๊ฐ ์ด๋ฉ์ผ์ ์ฒจ๋ถํด์ ๋ณด๋ธ, ํ๋ ฅ ์ ์ฒด ํด๋์ค๋ฅผ ์ดํด๋ณด์.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class OutdoorLight {
on() {
console.log("์กฐ๋ช
์ด ์ผ์ก์ต๋๋ค");
}
off() {
console.log("์กฐ๋ช
์ด ๊บผ์ก์ต๋๋ค");
}
}
class Stereo {
on() {
console.log("์ค๋์ค๊ฐ ์ผ์ก์ต๋๋ค");
}
off() {
console.log("์ค๋์ค๊ฐ ๊บผ์ก์ต๋๋ค");
}
setCd() {
console.log("CD๊ฐ ์ฌ์๋ฉ๋๋ค");
}
setVolume(volume: number) {
console.log(`๋ณผ๋ฅจ์ด ${volume}๋ก ์ค์ ๋์์ต๋๋ค`);
}
}
class TV {
on() {
console.log("TV๊ฐ ์ผ์ก์ต๋๋ค");
}
off() {
console.log("TV๊ฐ ๊บผ์ก์ต๋๋ค");
}
setInputChannel(channel: number) {
console.log("์ฑ๋์ด ${channel}๋ฒ์ผ๋ก ์ค์ ๋ฉ๋๋ค.")
}
}
๊ณตํต์ ์ธ ์ธํฐํ์ด์ค๊ฐ ์์ง๋ ์์ ๋ฟ๋๋ฌ, ์์ผ๋ก๋ ์ด๋ฐ ํด๋์ค๋ค์ด ๋ ์ถ๊ฐ๋ ์๋ ์๋ค.
๐ฎ ์ปค๋งจ๋ ํจํด ์๊ฐ
๊ฐ์ฒด๋ง์ ์๋น์์๋ ์ฃผ๋ฌธ์ ์ฒ๋ฆฌํ๋ ์๋ก์ด ์์คํ ์ ๋์ ํ๋ค.
๊ธฐ์กด ์์ ์ฃผ๋ฌธ ๊ณผ์
- ๊ณ ๊ฐ์ด ์ข ์ ์์์ ์ฃผ๋ฌธํ๋ค.
- ์ข ์ ์์ ์ฃผ๋ฌธ์ ๋ฐ์์ ์นด์ดํฐ์ ์ ๋ฌํ๊ณ โ์ฃผ๋ฌธ ๋ค์ด์์ด์!โ ๋ผ๊ณ ์๊ธฐํ๋ค.
- ์ฃผ๋ฐฉ์ฅ์ด ์ฃผ๋ฌธ๋๋ก ์์์ ์ค๋นํ๋ค.
๊ฐ์ฒด๋ง์ ์๋น์ธ ๋งํผ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํ์ฉํด ๋ณด์.
- ๊ณ ๊ฐ์ด ์ํ๋ ๊ฒ์ ์ฃผ๋ฌธํ๋ค.
- ์ฃผ๋ฌธ์ ์ฃผ๋ฌธ์์ ๊ทธ ์์ ์ ํ ์๋ ์ฃผ๋ฌธ ๋ด์ฉ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
- ์ข ์ ์์ ์ฃผ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ์ค๋นํ๋ orderUp() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- Order ๊ฐ์ฒด์๋ ์์์ ์ค๋นํ ๋ ํ์ํ ๋ชจ๋ ์ง์์ฌํญ์ด ๋ค์ด์๋ค. Order ๊ฐ์ฒด๊ฐ ์ฃผ๋ฐฉ์ฅ์๊ฒ makeBurger() ๊ฐ์ ๋ฉ์๋ ํธ์ถ๋ก ํ๋์ ์ง์ํ๋ค.
- ์ฃผ๋ฐฉ์ฅ์ Order๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ ์ง์์ฌํญ์ ๋ฐ๋ผ์ ์์์ ์ค๋นํ๋ค.
๐ฎ ๊ฐ์ฒด๋ง์ ์๋น ๋ฑ์ฅ์ธ๋ฌผ์ ์ญํ
- ์ฃผ๋ฌธ์๋ ์ฃผ๋ฌธ ๋ด์ฉ์ ์บก์ํํ๋ค.
- ์ฃผ๋ฌธ ๋ด์ฉ์ ์๊ตฌํ๋ ๊ฐ์ฒด๋ผ๊ณ ๋ณผ ์ ์๋ค. ์ด ๊ฐ์ฒด์ ์ธํฐํ์ด์ค์๋ ์์ฌ ์ค๋น์ ํ์ํ ํ๋์ ์บก์ํํ orderUp() ๋ฉ์๋๊ฐ ๋ค์ด์๋ค.
- ์ข
์
์์ ์ฃผ๋ฌธ์๋ฅผ ๋ฐ๊ณ orderUp() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- ์ข ์ ์์ ์ฃผ๋ฌธ์์ ๋ฌด์จ ๋ด์ฉ์ด ์๋์ง, ๋๊ฐ ์์ฌ๋ฅผ ์ค๋นํ๋์ง๋ ์ ํ ์ ํ์๊ฐ ์๋ค. ์ข ์ ์์ takeOrder() ๋ฉ์๋์๋ ์ฌ๋ฌ ๊ณ ๊ฐ์ ์ฃผ๋ฌธ์๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌํ๋ค.
- ์ฃผ๋ฐฉ์ฅ์ ์์ฌ๋ฅผ ์ค๋นํ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์๋ค.
- ์ข ์ ์์ด orderUp() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์ฃผ๋ฐฉ์ฅ์ด ๊ทธ ์ฃผ๋ฌธ์ ๋ฐ์์ ์์์ ๋ง๋ค ๋ ํ์ํ ๋ฉ์๋๋ฅผ ์ ๋ถ ์ฒ๋ฆฌํ๋ค. ์ฌ๊ธฐ์ ์ฃผ๋ฐฉ์ฅ๊ณผ ์ข ์ ์์ ์์ ํ ๋ถ๋ฆฌ๋์ด ์๋ค.
๊ฐ์ฒด๋ง์ ์๋น์ ๊ฐ์ฒด์งํฅ ๋์์ธ ํจํด์ ํญ ๋ชจ๋ธ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค. ๋ฆฌ๋ชจ์ปจ API์ ๋์ ํด ๋ณด๋ฉด, ๋ฆฌ๋ชจ์ปจ ๋ฒํผ์ด ๋๋ ธ์ ๋ ํธ์ถ๋๋ ์ฝ๋์ ์ค์ ๋ก ์ผ์ ์ฒ๋ฆฌํ๋ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํด์ผ ํ๋ค. ๋ฆฌ๋ชจ์ปจ ์ฌ๋กฏ์ ๊ฐ์ฒด๋ง์ ์๋น์ ์ฃผ๋ฌธ์ ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋ค์ด์๋ค๋ฉด ์ด๋จ๊น?
๐ฎ ๊ฐ์ฒด๋ง์ ์๋น๊ณผ ์ปค๋งจ๋ ํจํด
- ํด๋ผ์ด์ธํธ๋ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ค. ์ปค๋งจ๋ ๊ฐ์ฒด๋ ๋ฆฌ์๋ฒ์ ์ ๋ฌํ ์ผ๋ จ์ ํ๋์ผ๋ก ๊ตฌ์ฑ๋๋ค.
- ์ปค๋งจ๋ ๊ฐ์ฒด์๋ ํ๋๊ณผ ๋ฆฌ์๋ฒ์ ์ ๋ณด๊ฐ ๊ฐ์ด ๋ค์ด์๋ค.
- ์ปค๋งจ๋ ๊ฐ์ฒด์์ ์ ๊ณตํ๋ ๋ฉ์๋๋ execute() ํ๋๋ฟ์ด๋ค. ์ด ๋ฉ์๋๋ ํ๋์ ์บก์ํํ๋ฉฐ, ๋ฆฌ์๋ฒ์ ์๋ ํน์ ํ๋์ ์ฒ๋ฆฌํ๋ค.
- ํด๋ผ์ด์ธํธ๋ ์ธ๋ณด์ปค ๊ฐ์ฒด์ setCommand() ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ฐ, ์ด๋ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ค๋ค. ๊ทธ ์ปค๋งจ๋ ๊ฐ์ฒด๋ ๋์ค์ ์ฐ์ด๊ธฐ ์ ๊น์ง ์ธ๋ณด์ปค ๊ฐ์ฒด์ ๋ณด๊ด๋๋ค.
- ์ธํฌ์ปค์์ ์ปค๋งจ๋ ๊ฐ์ฒด์ execute() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ฆฌ์๋ฒ์ ์๋ ํ๋ ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
์ธ๋ณด์ปค ๋ก๋ฉ
- ํด๋ผ์ด์ธํธ์์ ์ปค๋งจ๋ ๊ฐ์ฒด ์์ฑ
- setCommand()๋ฅผ ํธ์ถํด์ ์ธ๋ณด์ปค์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์ ์ฅ
- ๋์ค์ ํด๋ผ์ด์ธํธ์์ ์ธ๋ณด์ปค์๊ฒ ๊ทธ ๋ช ๋ น์ ์คํํ๋ผ๊ณ ์์ฒญ
- ์ฐธ๊ณ : ์ด๋ค ๋ช ๋ น์ ์ธ๋ณด์ปค์ ๋ก๋ฉํ ๋ค์ ํ ๋ฒ๋ง ์์ ์ ์ฒ๋ฆฌํ๊ณ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์ง์ฐ๋๋ก ํ ์๋ ์๊ณ , ์ ์ฅํด ๋ ๋ช ๋ น์ ์ฌ๋ฌ ๋ฒ ์ํํ๊ฒ ํ ์๋ ์๋ค.
๐ฎ ์ฒซ ๋ฒ์งธ ์ปค๋งจ๋ ๊ฐ์ฒด ๋ง๋ค๊ธฐ
๋จผ์ ๊ณตํต ์ธํฐํ์ด์ค์ธย Command๋ฅผ ์ ์ํด ๋ณด์. ๋ชจ๋ ์ปค๋งจ๋ ๊ฐ์ฒด๋ ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ค.
1
2
3
interface Command {
execute(): void
}
์ด์ ์กฐ๋ช ์ ์ผค ๋ ํ์ํ ์ปค๋งจ๋ ํด๋์ค๋ฅผ ๊ตฌํํด ๋ณด์. ํ๋ ฅ ์ ์ฒด์์ ์ ๊ณตํ ํด๋์ค๋ฅผ ๋ณด๋ Light ํด๋์ค์๋ on()๊ณผ off()๋ผ๋ 2๊ฐ์ ๋ฉ์๋๊ฐ ์๋ค.
1
2
3
4
5
6
7
class LightOnCommand implements Command {
constructor(private light: OutdoorLight) {}
execute() {
this.light.on()
}
}
์์ฑ์์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ก ์ ์ดํ ํน์ ์กฐ๋ช (โ๊ฑฐ์ค ์กฐ๋ช โ ๋ฑ)์ ์ ๋ณด๊ฐ ์ ๋ฌ๋๋ค. ๊ทธ ๊ฐ์ฒด๋ light๋ผ๋ ์ธ์คํด์ค ๋ณ์์ ์ ์ฅ์ด ๋๋ค. execute() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด light ๊ฐ์ฒด๊ฐ ๋ฐ๋ก ๊ทธ ์์ฒญ์ ๋ฆฌ์๋ฒ๊ฐ ๋๋ค.
execute() ๋ฉ์๋๋ ๋ฆฌ์๋ฒ ๊ฐ์ฒด์ ์๋ on() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
๐ฎ ์ปค๋งจ๋ ๊ฐ์ฒด ์ฌ์ฉํ๊ธฐ
์ ์ดํ ๊ธฐ๊ธฐ๋ฅผ ์ฐ๊ฒฐํ ์ฌ๋กฏ๊ณผ ๋ฒํผ์ด ๊ฐ๊ฐ ํ๋์ฉ๋ฐ์ ์๋ ๋ฆฌ๋ชจ์ปจ์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด ๋ณด์.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Command {
execute(): void;
}
class SimpleRemoteControl {
private slot: Command | null = null;
setCommand(command: Command) {
this.slot = command;
}
buttonWasPressed() {
this.slot?.execute();
}
}
- ์ปค๋งจ๋๋ฅผ ์ ์ฅํ ์ฌ๋กฏ์ด 1๊ฐ ์๋ค. ์ด ์ฌ๋กฏ์ผ๋ก 1๊ฐ์ ๊ธฐ๊ธฐ๋ฅผ ์ ์ดํ๋ค.
- ์ฌ๋กฏ์ ๊ฐ์ง๊ณ ์ ์ดํ ๋ช
๋ น์ ์ค์ ํ๋ ๋ฉ์๋(setCommand)
- ๋ฆฌ๋ชจ์ปจ ๋ฒํผ์ ๊ธฐ๋ฅ์ ๋ฐ๊พธ๊ณ ์ถ๋ค๋ฉด ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ์ผ๋ง๋ ์ง ๋ฐ๊ฟ ์ ์๋ค.
- ๋ฒํผ์ ๋๋ฅด๋ฉด buttonWasPressed()๊ฐ ํธ์ถ๋๋ค. ์ง๊ธ ์ฌ๋กฏ์ ์ฐ๊ฒฐ๋ ์ปค๋งจ๋ ๊ฐ์ฒด์ execute() ๋ฉ์๋๋ง ํธ์ถํ๋ฉด ๋๋ค.
1
2
3
4
5
6
7
8
9
10
function simpleRemoteControlTest() {
const remoteControl = new SimpleRemoteControl(); // ์ธ๋ณด์ปค
const light = new Light(); // ๋ฆฌ์๋ฒ
const lightOn = new LightOnCommand(light); // ์ปค๋งจ๋ ๊ฐ์ฒด
remoteControl.setCommand(lightOn); // ์ปค๋งจ๋ ์ค์
remoteControl.buttonWasPressed(); // ์ปค๋งจ๋ ์คํ
}
simpleRemoteControlTest();
๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์จ์ SimpleRemoteControl๋ฅผ ํ ์คํธํด ๋ณด์.
- ๋ฆฌ๋ชจ์ปจ ์์ฑ (์ธ๋ณด์ปค): ๋ช ๋ น์ ๋ณด๊ดํ๊ณ , ์คํ์ ์์ฒญํ๋ ๊ฐ์ฒด
- ๋ถ ๋ง๋ค๊ธฐ (๋ฆฌ์๋ฒ): ์ค์ ์ผ์ ์ํํ๋ ๊ฐ์ฒด
- ๋ช ๋ น์ ๋ง๋ค๊ธฐ (์ปค๋งจ๋ ๊ฐ์ฒด): ๋ฆฌ์๋ฒ์๊ฒ ์ผ์ ์ํค๋ ๋ช ๋ น์ ์ญํ . execute() ๋ฉ์๋ ์์ โ๋ฌด์์ ํ ์งโ ์ ํ ์์
- ๋ฆฌ๋ชจ์ปจ์ ๋ช ๋ น์ ๊ฝ๊ธฐ (์ปค๋งจ๋ ์ค์ ) โ ๋ฒํผ ๋๋ฅด๊ธฐ (์ปค๋งจ๋ ์คํ)
GarageDoorOpenCommand ํด๋์ค๋ฅผ ๋ง๋ค์ด ์ฐจ๊ณ ๋ฌธ์ ์ด์ด ๋ณด์.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// ๋ฆฌ์๋ฒ: ์ค์ ๋์์ ์ํํ๋ ํด๋์ค
class GarageDoor {
lightOn() {
console.log("์ฐจ๊ณ ๋ถ์ด ์ผ์ก์ต๋๋ค");
}
garageOpen() {
console.log("์ฐจ๊ณ ๋ฌธ์ด ์ด๋ ธ์ต๋๋ค");
}
}
// ์ปค๋งจ๋ ์ธํฐํ์ด์ค
interface Command {
execute(): void;
}
// ์ปค๋งจ๋ ๊ตฌํ: ์ฐจ๊ณ ๋ฌธ ์ด๊ธฐ
class GarageDoorOpenCommand implements Command {
constructor(private garageDoor: GarageDoor) {}
execute() {
this.garageDoor.garageOpen();
}
}
// ์ปค๋งจ๋: ์ฐจ๊ณ ๋ถ ์ผ๊ธฐ
class GarageDoorLightOnCommand implements Command {
constructor(private garageDoor: GarageDoor) {}
execute() {
this.garageDoor.lightOn();
}
}
// ์ธ๋ณด์ปค: ์ปค๋งจ๋๋ฅผ ์ค์ ํ๊ณ ์คํํ๋ ๋ฆฌ๋ชจ์ปจ
class SimpleRemoteControl {
private slot: Command | null = null;
setCommand(command: Command) {
this.slot = command;
}
buttonWasPressed() {
this.slot?.execute();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function garageTest() {
const remote = new SimpleRemoteControl(); // ์ธ๋ณด์ปค
const garageDoor = new GarageDoor(); // ๋ฆฌ์๋ฒ
const openCommand = new GarageDoorOpenCommand(garageDoor); // ์ปค๋งจ๋: ๋ฌธ ์ด๊ธฐ
const lightOnCommand = new GarageDoorLightOnCommand(garageDoor); // ์ปค๋งจ๋: ๋ถ ์ผ๊ธฐ
// ์ฐจ๊ณ ๋ฌธ ์ด๊ธฐ
remote.setCommand(openCommand);
remote.buttonWasPressed(); // ์ถ๋ ฅ: ์ฐจ๊ณ ๋ฌธ์ด ์ด๋ ธ์ต๋๋ค
// ์ฐจ๊ณ ๋ถ ์ผ๊ธฐ
remote.setCommand(lightOnCommand);
remote.buttonWasPressed(); // ์ถ๋ ฅ: ์ฐจ๊ณ ๋ถ์ด ์ผ์ก์ต๋๋ค
}
garageTest();
๐ฎ ์ปค๋งจ๋ ํจํด์ ์ ์
์ปค๋งจ๋ ํจํด(Command Pattern)์ ์ฌ์ฉํ๋ฉด ์์ฒญ ๋ด์ญ์ ๊ฐ์ฒด๋ก ์บก์ํํด์ ๊ฐ์ฒด๋ฅผ ์๋ก ๋ค๋ฅธ ์์ฒญ ๋ด์ญ์ ๋ฐ๋ผ ๋งค๊ฐ๋ณ์ํํ ์ ์๋ค. ์ด๋ฌ๋ฉด ์์ฒญ์ ํ์ ์ ์ฅํ๊ฑฐ๋ ๋ก๊ทธ๋ก ๊ธฐ๋กํ๊ฑฐ๋ ์์ ์ทจ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
์ปค๋งจ๋ ๊ฐ์ฒด๋ ์ผ๋ จ์ ํ๋์ ํน์ ๋ฆฌ์๋ฒ์ ์ฐ๊ฒฐ์ํด์ผ๋ก์จ ์๊ตฌ ์ฌํญ์ ์บก์ํํ ๊ฒ์ด๋ค.
์ด๋ฌ๋ ค๋ฉด ํ๋๊ณผ ๋ฆฌ์๋ฒ๋ฅผ ํ ๊ฐ์ฒด์ ์ง์ด๋ฃ๊ณ execute()๋ผ๋ ๋ฉ์๋ ํ๋๋ง ์ธ๋ถ์ ๊ณต๊ฐํ๋ ๋ฐฉ๋ฒ์ ์จ์ผ ํ๋ค. ์ด ๋ฉ์๋ ํธ์ถ์ ์ํด์ ๋ฆฌ์๋ฒ์์ ์ผ๋ จ์ ์์ ์ด ์ฒ๋ฆฌ๋๋ค. ๋ฐ์์ ๋ณผ ๋๋ ์ด๋ค ๊ฐ์ฒด๊ฐ ๋ฆฌ์๋ฒ ์ญํ ์ ํ๋์ง, ๊ทธ ๋ฆฌ์๋ฒ์์ ์ค์ ๋ก ์ด๋ค ์ผ์ ํ๋์ง ์ ์ ์๋ค. execute()ย ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์๊ตฌ ์ฌํญ์ด ์ฒ๋ฆฌ๋๋ค๋ ๊ฒ๋ง ์ ์ ์์ ๋ฟ์ด๋ค.
๋ช ๋ น์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋งค๊ฐ๋ณ์ํํ๋ ๋ช ๊ฐ์ง ์ฌ๋ก๋ ๋ณผ ์ ์๋ค.
๊ฐ์ฒด๋ง์ ์๋น์์๋ ์ข ์ ์์ด ์ฌ๋ฌ ๊ฐ์ ์ฃผ๋ฌธ์๋ก ๋งค๊ฐ๋ณ์ํ๋๋ ๊ฒ์ ๋ณผ ์ ์์๊ณ , ๊ฐ๋จํ ๋ฆฌ๋ชจ์ปจ ์์ ์์๋ ๋ฒํผ ์ฌ๋กฏ์ โ์กฐ๋ช ์ผ๊ธฐโ ๋ช ๋ น์ ๋ก๋ฉํ๋ค๊ฐ ๋์ค์ โ์ฐจ๊ณ ๋ฌธ ์ด๊ธฐโ ๋ช ๋ น์ ๋ก๋ฉํ๊ธฐ๋ ํ๋ค.
์์ง ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์จ์ ํ์ ๋ก๊ทธ๋ฅผ ๊ตฌํํ๊ฑฐ๋ ์์ ์ทจ์๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ์ง ๋ชปํ๋ค. ํ์ง๋ง ๊ธฐ๋ณธ์ ์ธ ์ปค๋งจ๋ ํจํด์ ์กฐ๊ธ๋ง ํ์ฅํ๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ธฐ๋ณธ์ ์ธ ์ปค๋งจ๋ ํจํด์ ์ ๋๋ก ์ฌ์ฉํ ์ ์๋ค๋ฉด ๋ฉํ ์ปค๋งจ๋ ํจํด(Meta Command Partten)๋ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์๊ฒ ๊ตฌํํ ์ ์๋ค. ๋ฉํ ์ปค๋งจ๋ ํจํด์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ๊ฐ์ ๋ช ๋ น์ ๋งคํฌ๋ก๋ก ํ ๋ฒ์ ์คํํ ์ ์๋ค.
๐ฎ ์ปค๋งจ๋ ํจํด ํด๋์ค ๋ค์ด์ด๊ทธ๋จ ์ดํด๋ณด๊ธฐ
- Client (ํด๋ผ์ด์ธํธ)
- ์ค์ ๋ช ๋ น์ ๋ง๋ค๊ณ ๋ฆฌ์๋ฒ๋ฅผ ์ค์ ํ๋ ์ญํ ์ ํ๋ค.
- ์: โ๋ถ ์ผ๊ธฐโ ๋ช ๋ น์ ๋ง๋ค๊ณ , ์ด๋ค ์กฐ๋ช ์ ์ผค์ง ์ง์ ํ๋ค.
- Command (๋ช
๋ น ์ธํฐํ์ด์ค)
- ๋ชจ๋ ๋ช ๋ น์ด ๋ฐ๋ผ์ผ ํ๋ ๊ณตํต ์ธํฐํ์ด์ค๋ค.
- ๋ณดํตย execute()ย ๋ฉ์๋๋ง ๊ฐ์ง๋ค.
- ConcreteCommand (๊ตฌ์ฒด ๋ช
๋ น ๊ฐ์ฒด)
- ์ค์ ๋ช ๋ น ๋ด์ฉ์ด ๋ค์ด ์๋ ํด๋์ค๋ค.
- ๋ฆฌ์๋ฒ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ,ย execute()ย ์์์ ๋ฆฌ์๋ฒ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- ์:ย this.light.on()์ฒ๋ผ ์ค์ ๋์์ ์ํํ๋ค.
- Receiver (๋ฆฌ์๋ฒ)
- ์ค์ ์ผ์ ์ํํ๋ ๊ฐ์ฒด๋ค.
- ๋ช ๋ น ๊ฐ์ฒด์์ ์ด ๋ฆฌ์๋ฒ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- ์: Light, GarageDoor ๋ฑ
- Invoker (์ธ๋ณด์ปค)
- ๋ช ๋ น์ ๋ฐ์ ์ ์ฅํ๊ณ ์๋ค๊ฐ, ํ์ํ ๋ย execute()๋ฅผ ํธ์ถํ๋ ์ญํ ์ ํ๋ค.
- ์: ๋ฆฌ๋ชจ์ปจ, ๋ฒํผ
์ปค๋งจ๋ ํจํด์ ์ฌ์ฉํ๋ฉด ์์ ์ ์๊ตฌํ ์ธ๋ณด์ปค์ ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฆฌ์๋ฒ๊ฐ ์ด๋ป๊ฒ ๋ถ๋ฆฌ๋๋ ๊ฑธ๊น?
๊ตฌ์กฐ์ ๋ฐ๋ฅธ ์ญํ ๋ถ๋ฆฌ
| ๊ตฌ์ฑ ์์ | ์ญํ | ์๊ฑฐ๋ ๋ชจ๋ฅด๋ ๊ฒ |
|---|---|---|
| Invoker (์: ๋ฆฌ๋ชจ์ปจ) | ๋ช
๋ น์ ์ ์ฅํ๊ณ , ์คํ์ย execute()๋ง ํธ์ถ | ๋ฆฌ์๋ฒ๊ฐ ๋ญ์ง, ์ค์ ํ๋์ด ๋ญ์งย ๋ชจ๋ฆ |
| Command (๋ช ๋ น์) | ๋ฆฌ์๋ฒ์ ํ๋์ ๋ด๋ถ์ ๋ด๊ณ ์์ | execute()ย ์์์ ๋ฆฌ์๋ฒ์ ๋ฉ์๋ ํธ์ถ |
| Receiver (์: ์กฐ๋ช , TV) | ์ง์ง๋ก ์ผ์ ์ํํ๋ ๊ฐ์ฒด | ์ค์ ํ๋์ ๊ตฌํ |
1
2
remote.setCommand(lightOnCommand); // remote๋ ๊ทธ๊ฒ ๋ญ์ง ๋ชจ๋ฆ
remote.buttonWasPressed(); // ๋ด๋ถ์ ์ผ๋ก light.on() ์คํ๋จ
remote(์ธ๋ณด์ปค)๋ ๊ทธ๋ฅยexecute()๋ง ํธ์ถlightOnCommand(์ปค๋งจ๋ ๊ฐ์ฒด)๋ ๋ด๋ถ์ ์ผ๋กยlight.on()ย ํธ์ถlight(๋ฆฌ์๋ฒ)๊ฐ ์ค์ ๋ก ๋ถ์ ์ผ ๋ค
์ ์ด๊ฒ ์ข์๊น?
- ์ธ๋ณด์ปค๋ย ๋ชจ๋ํ, ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ฆฌ์๋ฒ๋ย ๋์์๋ง ์ง์ค
- ์ปค๋งจ๋๋ฅผ ๋ฐ๊ฟ ๋ผ์ฐ๋ฉดย ๋์์ ์ ์ฐํ๊ฒ ๋ณ๊ฒฝ ๊ฐ๋ฅ
์ฆ, ์ปค๋งจ๋ ํจํด์ ์ค๊ฐ์ย ๋ช ๋ น ๊ฐ์ฒด๋ฅผ ๋ผ์ ๋ฃ์ด โ๋๊ฐ ๋ช ๋ นํ๊ณ , ๋๊ฐ ์ํํ๋์งโ๋ฅผ ๋์จํ๊ฒ ์ฐ๊ฒฐํ๋ ๊ฒ ํต์ฌ์ด๋ค.
๐ฎ ์ฌ๋กฏ์ ๋ช ๋ น ํ ๋นํ๊ธฐ
- ๊ฐ ์ฌ๋กฏ๋ง๋ค ์ปค๋งจ๋ ๊ฐ์ฒด๊ฐ ํ ๋น๋๋ค.
- ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋น ์ปค๋งจ๋ ๊ฐ์ฒด์ execute() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
- execute() ๋ฉ์๋์์๋ ๋ฆฌ์๋ฒ๋ก ํ์ฌ๊ธ ํน์ ์์ ์ ์ฒ๋ฆฌํ๋๋ก ์ง์ํ๋ค.
๐ฎย ๋ฆฌ๋ชจ์ปจ ์ฝ๋ ๋ง๋ค๊ธฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// ์ปค๋งจ๋ ์ธํฐํ์ด์ค
interface Command {
execute(): void;
}
// ์๋ฌด ๋์๋ ํ์ง ์๋ ๊ธฐ๋ณธ ์ปค๋งจ๋ (Null Object ํจํด)
class NoCommand implements Command {
execute() {
// ์๋ฌด ์ผ๋ ํ์ง ์์
}
}
// ์ธ๋ณด์ปค ์ญํ ์ ๋ฆฌ๋ชจ์ปจ ํด๋์ค
class RemoteControl {
private static readonly SLOT_SIZE = 7; // ์ฌ๋กฏ ๊ฐ์: 7๊ฐ
private onCommands: Command[]; // ๊ฐ ์ฌ๋กฏ์ ON ์ปค๋งจ๋ ๋ฐฐ์ด
private offCommands: Command[]; // ๊ฐ ์ฌ๋กฏ์ OFF ์ปค๋งจ๋ ๋ฐฐ์ด
constructor() {
const noCommand = new NoCommand(); // ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ฃ์ ๋ช
๋ น
// ๋ชจ๋ ์ฌ๋กฏ์ NoCommand๋ก ์ด๊ธฐํ
this.onCommands = new Array(RemoteControl.SLOT_SIZE).fill(noCommand);
this.offCommands = new Array(RemoteControl.SLOT_SIZE).fill(noCommand);
}
// ์ฌ๋กฏ ๋ฒํธ์ ON/OFF ๋ช
๋ น์ ๋ฑ๋กํ๋ ๋ฉ์๋
setCommand(slot: number, onCommand: Command, offCommand: Command) {
this.onCommands[slot] = onCommand;
this.offCommands[slot] = offCommand;
}
// ON ๋ฒํผ ๋๋ ์ ๋ ์คํ๋๋ ๋ฉ์๋
onButtonWasPushed(slot: number) {
this.onCommands[slot].execute();
}
// OFF ๋ฒํผ ๋๋ ์ ๋ ์คํ๋๋ ๋ฉ์๋
offButtonWasPushed(slot: number) {
this.offCommands[slot].execute();
}
// ํ์ฌ ๋ฆฌ๋ชจ์ปจ์ ์ค์ ๋ ๋ช
๋ น ๋ชฉ๋ก์ ๋ฌธ์์ด๋ก ์ถ๋ ฅ
toString(): string {
let result = "\n------ Remote Control -------\n";
for (let i = 0; i < RemoteControl.SLOT_SIZE; i++) {
result += `[slot ${i}] ${this.onCommands[i].constructor.name} ${this.offCommands[i].constructor.name}\n`;
}
return result;
}
}
- ์ ์ฒด ์ฌ๋กฏ ์๋ 7๊ฐ๋ก ๊ณ ์ ๋์ด ์๋ค.
- on, off ๋ช ๋ น์ ๊ฐ๊ฐ ๋ฐฐ์ด๋ก ์ ์ฅํ๋ค.
- ์ด๊ธฐ์๋ ๋ชจ๋ ์ฌ๋กฏ์ ์๋ฌด ๋์๋ ํ์ง ์๋ NoCommand ๊ฐ์ฒด๋ฅผ ๋ฃ์ด๋๋ค
- setCommand๋ก ํน์ ์ฌ๋กฏ์ on๊ณผ off ๋ช ๋ น์ ์ค์ ํ ์ ์๋ค
- onButtonWasPushed๋ ํด๋น ์ฌ๋กฏ์ on ๋ช ๋ น์ ์คํํ๋ค
- offButtonWasPushed๋ ํด๋น ์ฌ๋กฏ์ off ๋ช ๋ น์ ์คํํ๋ค
- toString ๋ฉ์๋๋ ํ์ฌ ์ฌ๋กฏ์ ์ด๋ค ๋ช ๋ น๋ค์ด ๋ค์ด์๋์ง ๋ฌธ์์ด๋ก ์ถ๋ ฅํ๋ค
๐ฎย ์ปค๋งจ๋ ํด๋์ค ๋ง๋ค๊ธฐ
์์์ SimpleRemoteControl์ ๋ง๋ค ๋ LightOnCommand๋ผ๋ ์ปค๋งจ๋ ํด๋์ค๋ฅผ ๋ง๋ ์ ์ด ์๋ค. ๊ทธ ์ฝ๋๋ฅผ ์ฌ๊ธฐ์ ๊ทธ๋๋ก ์ธ ์ ์๋ค. ์กฐ๋ช ์ ๋ ๋ ์ฐ๋ LightOffCommand๋ผ๋ ์ปค๋งจ๋ ํด๋์ค๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ง๋ค๋ฉด ๋๋ค.
1
2
3
4
5
6
7
class LightOffCommand implements Command {
constructor(private light: OutdoorLight) {}
execute() {
this.light.off()
}
}
์ค๋์ค๋ฅผ ์ผ๊ณ ๋ ๋ ์ฌ์ฉํ ์ปค๋งจ๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด ๋ณด์. ๋๋ ๊ฑด off() ๋ฉ์๋์ ์ฐ๊ฒฐํด ์ฃผ๋ฉด ๋์ง๋ง, ์ผ๋ ๊ฑด ์กฐ๊ธ ๋ ์ด๋ ต๋ค. ์ผ๋จ ์ค๋์ค๋ฅผ ์ผค ๋ ์๋์ผ๋ก CD๊ฐ ์ฌ์๋๋๋ก ํ๋ stereoOnWithCDCommand ํด๋์ค๋ฅผ ๋ง๋ค์ด ๋ณด์.
1
2
3
4
5
6
7
8
9
class StereoOnWithCDCommand implements Command {
constructor(private stereo: Stereo) {}
execute() {
this.stereo.on();
this.stereo.setCd();
this.stereo.setVolume(11);
}
}
๐ฎย ๋ฆฌ๋ชจ์ปจ ํ ์คํธ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function RemoteLoader() {
const remoteControl = new RemoteControl();
const livingRoomLight = new Light("๊ฑฐ์ค");
const kitchenLight = new Light("์ฃผ๋ฐฉ");
const ceilingFan = new CeilingFan("๊ฑฐ์ค");
const garageDoor = new GarageDoor("์ฐจ๊ณ ");
const stereo = new Stereo("๊ฑฐ์ค");
const livingRoomLightOn = new LightOnCommand(livingRoomLight);
const livingRoomLightOff = new LightOffCommand(livingRoomLight);
const kitchenLightOn = new LightOnCommand(kitchenLight);
const kitchenLightOff = new LightOffCommand(kitchenLight);
const ceilingFanOn = new CeilingFanOnCommand(ceilingFan);
const ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
const garageDoorUp = new GarageDoorUpCommand(garageDoor);
const garageDoorDown = new GarageDoorDownCommand(garageDoor);
const stereoOnWithCD = new StereoOnWithCDCommand(stereo);
const stereoOff = new StereoOffCommand(stereo);
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff);
remoteControl.setCommand(3, stereoOnWithCD, stereoOff);
console.log(remoteControl.toString());
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(2);
remoteControl.onButtonWasPushed(3);
remoteControl.offButtonWasPushed(3);
}
RemoteLoader();
4๋ฒ๋ถํฐ 6๋ฒ ์ฌ๋กฏ๊น์ง๋ NoCommand๋ผ๊ณ ๋์ค๋๋ฐ ๊ทธ๊ฑด ๋ญ๊น?
- NoCommand ๊ฐ์ฒด
- NoCommand ๊ฐ์ฒด๋ ์ผ์ข ์ ๋ ๊ฐ์ฒด์ด๋ค. ๋ฑํ ๋ฆฌํดํ ๊ฐ์ฒด๋ ์์ง๋ง ํด๋ผ์ด์ธํธ ์ชฝ์์ null์ ์ฒ๋ฆฌํ์ง ์์๋ ๋๋๋ก ํ๊ณ ์ถ์ ๋ ๋ ๊ฐ์ฒด๋ฅผ ํ์ฉํ๋ฉด ์ข๋ค. ํน์ ์ฌ๋กฏ์ ์ฐ๋ ค๊ณ ํ ๋ ๋ง๋ค ๊ฑฐ๊ธฐ์ ๋ญ๊ฐ๊ฐ ๋ก๋ฉ๋์ด ์๋์ง ํ์ธํ๋ ค๋ฉด ์ข ๊ท์ฐฎ๊ธฐ ๋๋ฌธ์ด๋ค.
๐ฎย API ๋ฌธ์ ๋ง๋ค๊ธฐ
- Command
- ๋ชจ๋ RemoteControl ํด๋์ค์ฉ ์ปค๋งจ๋ ๊ฐ์ฒด๋ Command๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
- ์ปค๋งจ๋ ๊ฐ์ฒด๋ ์ผ๋ จ์ ํ๋์ ์บก์ํํ๋ฉฐ, ๋ฆฌ๋ชจ์ฝ์ ํด๋น ํ๋์ execute(), undo()๋ฅผ ํตํด ํธ์ถํ๋ค.
- LightOnCommand, LightOffCommand
- ๋ฆฌ๋ชจ์ฝ์ ๋๋ ์๋ ํธ์ถ๋๋ ํ๋์ด๋ค. Command ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ปค๋งจ๋ ๊ฐ์ฒด๋ก ๊ตฌํ๋๋ค.
- ์ปค๋งจ๋ ๊ฐ์ฒด์๋ ์ ์ฒด์์ ์ ๊ณตํ ํด๋์ค ์ธ์คํด์ค์ ๋ ํผ๋ฐ์ค๊ฐ ์กด์ฌํ์ฌ, execute()-undo()๋ก ๊ตฌํ๋์ด ์๋ค.
- RemoteControl
- ๋ฒํผ๋ง๋ค ํ๋์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ํ ๋นํด์ ๊ด๋ฆฌํ๋ค.
- ๋ฒํผ์ด ๋๋ฆฌ๋ฉด ๋ฒํผ์ ํด๋นํ๋ ButtonWasPushed()๊ฐ ํธ์ถ๋์ด execute()๋ฅผ ํธ์ถํ๋ค.
- Light
- ํ๋ ฅ์ ์ฒด๊ฐ ์ ๊ณตํ ํด๋์ค๋ก, Light ํด๋์ค๋ฅผ ์๋ก ๋ค์์ต๋๋ค.
- RemoteLoader
- ๋ฆฌ๋ชจ์ฝ ์ฌ๋กฏ์ ๋ก๋ฉ๋๋ ์ผ๋ จ์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- ๊ฐ ์ปค๋งจ๋ ๊ฐ์ฒด์๋ ํ ์คํ ๋ฉ์ด์ ์ฅ์น๋ก ์ ์ก๋๋ ์์ฒญ์ด ์บก์ํ๋์ด ์๋ค.
๐ฎย ์์ ์ทจ์ ๊ธฐ๋ฅ ์ถ๊ฐํ๊ธฐ
๋ฆฌ๋ชจ์ปจ์ ์์ ์ ์ทจ์ํ๋ UNDO ๋ฒํผ์ ์ถ๊ฐํด์ผ ํ๋ค. ๋ ๋ณต์กํ ์๋ฅผ ์ดํด๋ณด๊ธฐ ์ ์ ์ฐ์ ์กฐ๋ช ์์ ์ทจ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํด ๋ณด์.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
interface Command {
execute(): void;
undo(): void;
}
class LightOnCommand implements Command {
constructor(private light: Light) {}
execute() {
this.light.on();
}
undo() {
this.light.off(); // ์ด์ ์ํ๋ก ๋๋๋ฆฌ๊ธฐ
}
}
class LightOffCommand implements Command {
constructor(private light: Light) {}
execute() {
this.light.off();
}
undo() {
this.light.on(); // ์ด์ ์ํ๋ก ๋๋๋ฆฌ๊ธฐ
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class RemoteControl {
private static readonly SLOT_SIZE = 7;
private onCommands: Command[];
private offCommands: Command[];
private undoCommand: Command;
constructor() {
const noCommand = new NoCommand();
this.onCommands = new Array(RemoteControl.SLOT_SIZE).fill(noCommand);
this.offCommands = new Array(RemoteControl.SLOT_SIZE).fill(noCommand);
this.undoCommand = noCommand;
}
setCommand(slot: number, onCommand: Command, offCommand: Command) {
this.onCommands[slot] = onCommand;
this.offCommands[slot] = offCommand;
}
onButtonWasPushed(slot: number) {
this.onCommands[slot].execute();
this.undoCommand = this.onCommands[slot];
}
offButtonWasPushed(slot: number) {
this.offCommands[slot].execute();
this.undoCommand = this.offCommands[slot];
}
undoButtonWasPushed() {
this.undoCommand.undo();
}
}
๐ฎย ์์ ์ทจ์ ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ์ํ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
Light ํด๋์ค์ ์์ ์ทจ์ ๊ธฐ๋ฅ์ ๋ฐฐ์ ๋๋ฐ, ์์ ์ทจ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค ๋ณด๋ฉด ๊ฐ๋จํ ์ํ๋ฅผ ์ ์ฅํด์ผ ํ๋ ์ํฉ๋ ์ข ์ข ์๊ธด๋ค. ์ ํ๊ธฐ ์ ์กฐ ์ ์ฒด์์ ์ ๊ณตํ CeilingFan ํด๋์ค๋ก ๊ฐ๋จํ ์ํ๋ฅผ ์ ์ฅํด ๋ณด์. ์ ํ๊ธฐ๋ ์๋๋ฅผ ์ ํํ ์ ์๋ค๋ ์ฌ์ค์ ์์๋์.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class CeilingFan {
static readonly HIGH = 3;
static readonly MEDIUM = 2;
static readonly LOW = 1;
static readonly OFF = 0;
private speed: number;
constructor(private location: string) {
this.speed = CeilingFan.OFF;
}
high() {
this.speed = CeilingFan.HIGH;
console.log(`${this.location} ceiling fan is on high`);
}
medium() {
this.speed = CeilingFan.MEDIUM;
console.log(`${this.location} ceiling fan is on medium`);
}
low() {
this.speed = CeilingFan.LOW;
console.log(`${this.location} ceiling fan is on low`);
}
off() {
this.speed = CeilingFan.OFF;
console.log(`${this.location} ceiling fan is off`);
}
getSpeed(): number {
return this.speed;
}
}
๐ฎย ์ ํ๊ธฐ ๋ช ๋ น์ด์ ์์ ์ทจ์ ๊ธฐ๋ฅ ์ถ๊ฐํ๊ธฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class CeilingFanHighCommand implements Command {
private prevSpeed: number;
constructor(private ceilingFan: CeilingFan) {
this.prevSpeed = CeilingFan.OFF;
}
execute() {
this.prevSpeed = this.ceilingFan.getSpeed(); // ์คํ ์ ์ํ ์ ์ฅ
this.ceilingFan.high(); // ํ์ฌ ํ๋ ์คํ
}
undo() {
// ์ด์ ์๋ ์ํ๋ก ๋๋๋ฆฌ๊ธฐ
switch (this.prevSpeed) {
case CeilingFan.HIGH:
this.ceilingFan.high();
break;
case CeilingFan.MEDIUM:
this.ceilingFan.medium();
break;
case CeilingFan.LOW:
this.ceilingFan.low();
break;
default:
this.ceilingFan.off();
}
}
}
๐ฎย ์ ํ๊ธฐ ํ ์คํธ ์ฝ๋ ๋ง๋ค๊ธฐ
๋ฆฌ๋ชจ์ปจ์ ์ ํ๊ธฐ์ฉ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ๋ฃ์ด ํ ์คํธํด ๋ณผ ๋๊ฐ ๋์๋ค. 0๋ฒ ์ฌ๋กฏ์ ON ๋ฒํผ์ ์ ํ๊ธฐ ์๋๋ฅผ MEDIUM์ผ๋ก ์ค์ ํ๋ ๊ธฐ๋ฅ์, 1๋ฒ ์ฌ๋กฏ์ ON ๋ฒํผ์ ์ ํ๊ธฐ ์๋๋ฅผ HIGH๋ก ์ค์ ํ๋ ๊ธฐ๋ฅ์ ํ ๋นํ ๊ฒ์ด๋ค. OFF ๋ฒํผ์๋ ์๋๋ฅผ OFF๋ก ์ค์ ํ๋ ๊ธฐ๋ฅ์ ํ ๋นํ ๊ฒ์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function RemoteLoader() {
const remoteControl = new RemoteControl(); // ์ธ๋ณด์ปค
const ceilingFan = new CeilingFan("๊ฑฐ์ค"); // ๋ฆฌ์๋ฒ
// ์ปค๋งจ๋ ๊ฐ์ฒด ์์ฑ
const ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
const ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
const ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
// ์ฌ๋กฏ ์ค์
remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff); // 0๋ฒ ์ฌ๋กฏ: MEDIUM โ OFF
remoteControl.setCommand(1, ceilingFanHigh, ceilingFanOff); // 1๋ฒ ์ฌ๋กฏ: HIGH โ OFF
// ํ
์คํธ ์๋๋ฆฌ์ค
remoteControl.onButtonWasPushed(0); // ๊ฑฐ์ค ์ ํ๊ธฐ MEDIUM ์ค์
remoteControl.offButtonWasPushed(0); // ๊ฑฐ์ค ์ ํ๊ธฐ OFF
remoteControl.undoButtonWasPushed(); // ์ด์ ์ํ(MEDIUM) ๋ณต์
remoteControl.onButtonWasPushed(1); // ๊ฑฐ์ค ์ ํ๊ธฐ HIGH ์ค์
remoteControl.undoButtonWasPushed(); // ์ด์ ์ํ(OFF) ๋ณต์
}
๐ฎย ์ฌ๋ฌ ๋์์ ํ ๋ฒ์ ์ฒ๋ฆฌํ๊ธฐ
๋ฒํผ ํ ๊ฐ๋ง ๋๋ฅด๋ฉด ์กฐ๋ช ์ด ์ด๋์ด์ค์ง๋ฉด์ ์ค๋์ค์ TV๊ฐ ์ผ์ง๊ณ , DVD ๋ชจ๋๋ก ๋ณ๊ฒฝ๋๊ณ , ์์กฐ์ ๋ฌผ์ด ์ฑ์์ง๋ ๊ฒ๊น์ง ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ ๊ธฐ๋ฅ์ด ์์ด์ผ ์ง์ ํ ๋ฆฌ๋ชจ์ปจ์ด๋ผ๊ณ ํ ์ ์์ง ์์๊น?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MacroCommand implements Command {
constructor(private commands: Command[]) {}
execute() {
for (const command of this.commands) {
command.execute();
}
}
undo() {
// ์ญ์์ผ๋ก undo ์คํ
for (let i = this.commands.length - 1; i >= 0; i--) {
this.commands[i].undo();
}
}
}
๐ฎย ๋งคํฌ๋ก ์ปค๋งจ๋ ์ฌ์ฉํ๊ธฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function RemoteLoader() {
const remoteControl = new RemoteControl(); // ์ธ๋ณด์ปค
const light = new Light("Living Room"); // ๋ฆฌ์๋ฒ 1
const stereo = new Stereo("Living Room"); // ๋ฆฌ์๋ฒ 2
const lightOnCommand = new LightOnCommand(light);
const lightOffCommand = new LightOffCommand(light);
const stereoOnCommand = new StereoOnWithCDCommand(stereo);
const stereoOffCommand = new StereoOffCommand(stereo);
const partyOn: Command[] = [lightOnCommand, stereoOnCommand];
const partyOff: Command[] = [lightOffCommand, stereoOffCommand];
const partyOnMacro = new MacroCommand(partyOn);
const partyOffMacro = new MacroCommand(partyOff);
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
console.log(remoteControl.toString());
console.log("---- macro on ------");
remoteControl.onButtonWasPushed(0);
console.log("---- macro off ------");
remoteControl.offButtonWasPushed(0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
------ Remote Control -------
[slot 0] MacroCommand MacroCommand
[slot 1] NoCommand NoCommand
[slot 2] NoCommand NoCommand
[slot 3] NoCommand NoCommand
[slot 4] NoCommand NoCommand
[slot 5] NoCommand NoCommand
[slot 6] NoCommand NoCommand
---- macro on ------
Living Room light is on
Living Room stereo is on
CD๊ฐ ์ฌ์๋ฉ๋๋ค
๋ณผ๋ฅจ์ด 11๋ก ์ค์ ๋์์ต๋๋ค
---- macro off ------
Living Room light is off
Living Room stereo is off
- ์ปค๋งจ๋ ๊ฐ์ฒด๋ ํญ์ ๋ฆฌ์๋ฒ๊ฐ ํ์ํ ๊น?
- ๊ผญ ๊ทธ๋ฐ ๊ฑด ์๋๋ค. ์ปค๋งจ๋ ๊ฐ์ฒด ์์ฒด์์ ์คํ ๋ก์ง์ ์ฒ๋ฆฌํ๋ย โ์ค๋งํธ ์ปค๋งจ๋โย ๋ฅผ ๋ง๋ค ์๋ ์๋ค.
- ํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก๋ ๋ฆฌ์๋ฒ์ ์๋ ํ๋์ ๋จ์ํ ํธ์ถํ๋ย โ๋๋ฏธ ์ปค๋งจ๋โย ๋ฅผ ์ฌ์ฉํ๋ค.
- ์ด์ ๋ ๋ช ๋ น๊ณผ ์ค์ ์์ ์ ๋ถ๋ฆฌํ๊ณ ,ย ์ธ๋ณด์ปค์ ๋ฆฌ์๋ฒ๋ฅผ ๋์จํ๊ฒ ์ฐ๊ฒฐํ๊ธฐ ์ํด์๋ค.
- ์ปค๋งจ๋ ์์์ ๋ค ์ฒ๋ฆฌํ๋ฉด ๋์ค์ย ์ ์ฐ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ด ๋จ์ด์ง ์ ์๋ค.
- Undo(์์
์ทจ์)๋ฅผ ์ฌ๋ฌ ๋ฒ ๊ฐ๋ฅํ๊ฒ ํ๋ ค๋ฉด?
- ๋จ์ํ ๋ง์ง๋ง ์ปค๋งจ๋ ํ๋๋ง ๊ธฐ์ตํ๋ ๋์ ,ย ์คํํ ์ปค๋งจ๋๋ค์ ์คํ์ ์์๋๋ฉด ๋๋ค.
- ์ฌ์ฉ์๊ฐ Undo ๋ฒํผ์ ๋๋ฅผ ๋๋ง๋ค ์คํ์์ย ๊ฐ์ฅ ์ต๊ทผ ์ปค๋งจ๋๋ฅผ ๊บผ๋ด์ undo()๋ฅผ ํธ์ถํ๋ฉด ๋๋ค.
- ์ฆ,ย ํ์คํ ๋ฆฌ ์คํ์ ์ด์ฉํด ์ฌ๋ฌ ๋จ๊ณ undo๋ฅผ ๊ตฌํํ ์ ์๋ค.
- ํํฐ ๋ชจ๋ ๊ฐ์ ๋งคํฌ๋ก ๊ธฐ๋ฅ์ ์ง์ ๊ตฌํํด๋ ๋ ๊น?
- ๋ฌผ๋ก ๊ฐ๋ฅํ์ง๋ง,ย PartyCommand ์์ ๋ชจ๋ ์ฝ๋๋ฅผ ์ง์ ๋ฃ๋ ๋ฐฉ์์ ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ค.
- ๋์ ย MacroCommand๋ฅผ ์ฌ์ฉํ๋ฉดย ์ฌ๋ฌ ์ปค๋งจ๋๋ฅผ ๋ฌถ์ด์ ์คํํ ์ ์๊ณ ,
- ๋์ค์ ๋ณ๊ฒฝ์ด๋ ํ์ฅํ ๋๋ ๋ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
- ๊ฒฐ๋ก : ์ง์ ์ฒ๋ฆฌ๋ณด๋คย MacroCommandย ๋ฐฉ์์ดย ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์ ์ธก๋ฉด์์ ํจ์ฌ ๋ซ๋ค.
๐ฎย ์ปค๋งจ๋ ํจํด ํ์ฉํ๊ธฐ
์ปค๋งจ๋ ํจํด์ ํ์ฉํ๋ฉดย ์ปดํจํ ์ด์ ์ ์ผ๋ถ๋ถ(๋ฆฌ์๋ฒ + ํ๋)ย ์ ํ๋์ ๊ฐ์ฒด๋ก ์บก์ํํด์, ๊ทธ ๊ฐ์ฒด๋ฅผย ์ผ๊ธ ๊ฐ์ฒด์ฒ๋ผ ์ ๋ฌํ๊ฑฐ๋ย ๋์ค์ ์คํํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
์ฆ, ํด๋ผ์ด์ธํธ์์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋๊ณ ย ์ค๋ ์๊ฐ์ด ์ง๋ ํ์๋ ์คํํ ์ ์์ผ๋ฉฐ, ๋ค๋ฅธ ์ค๋ ๋์์ ์คํํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
์ด๋ฌํ ํน์ฑ์ ํ์ฉํ๋ฉด ์ปค๋งจ๋ ํจํด์ย ์ค์ผ์ค๋ฌ,ย ์ค๋ ๋ ํ,ย ์์ ํย ๊ฐ์ ๊ตฌ์กฐ์ ์ ์ฉํ ์ ์๋ค.
์์ ํ ๊ตฌ์กฐ ์์
- ์ปค๋งจ๋ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๊ฐ์ฒด๋ฅผ ํ์ ๋ฃ๋๋ค.
- ํ์ ํ์ชฝ ๋์๋ย ์์ ์ ๋ฑ๋กํ๋ ์ฝ๋๊ฐ ์๊ณ ,
- ๋ฐ๋์ชฝ ๋์๋ย ์์ ์ ์ฒ๋ฆฌํ๋ ์ค๋ ๋๋ค์ด ๋๊ธฐ ์ค์ด๋ค.
- ์ค๋ ๋๋ ํ์์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ๊บผ๋ธ ํ,ย execute() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- ์์ ์ด ๋๋๋ฉด ํด๋น ์ปค๋งจ๋ ๊ฐ์ฒด๋ ๋ฒ๋ ค์ง๊ณ , ๋ค์ ์ปค๋งจ๋๋ฅผ ์ฒ๋ฆฌํ๋ค.
์ ์ด ๊ตฌ์กฐ๊ฐ ์ ์ฉํ ๊น?
- ์์ ํ๋ ์ค์ ์์ ๋ด์ฉ(๊ณ์ฐ, ๋ค์ด๋ก๋ ๋ฑ)์ ์ ํ์๊ฐ ์๋ค.
- ๊ทธ์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ง ํ์ ๋ค์ด์ค๋ฉด ์ค๋ ๋๊ฐ ์์์ ์ฒ๋ฆฌํด์ค๋ค.
- ์๋ฅผ ๋ค์ด, ํ ์ค๋ ๋๊ฐย ๊ธ์ต ๊ณ์ฐ์ ํ๋ค๊ฐ, ๋ค์์ย ํ์ผ์ ๋ค์ด๋ก๋ํ ์๋ ์๋ค.
์์ ํ๋ย ์ค์ง ์ปค๋งจ๋ ๊ฐ์ฒด์ execute()๋ง ํธ์ถํ ๋ฟ์ด๋ฏ๋ก,
์์ ์ ์ข ๋ฅ์ ์ ํ ์์กดํ์ง ์๋ย ๋์จํ ๊ตฌ์กฐ๋ฅผ ์ ์งํ ์ ์๋ค.
์์ฝ
- ์ปค๋งจ๋ ๊ฐ์ฒด๋ย ์์ ๋จ์๋ฅผ ์ถ์ํํ ๊ฐ์ฒด์ด๋ค.
- ์ด ๊ฐ์ฒด๋ฅผ ํ์ ๋ด๊ณ ,ย ๋์ค์ ํ์ํ ๋ ์คํํ ์ ์๋ค.
- ์ด๋ฐ ๊ตฌ์กฐ๋ย ๋น๋๊ธฐ ์ฒ๋ฆฌ,ย ์ค๋ ๋ ๋ถ๋ฆฌ,ย ์ ์ฐํ ์์ ๊ด๋ฆฌย ๋ฑ์ ๋งค์ฐ ํจ๊ณผ์ ์ด๋ค.
๐ฎย ์ปค๋งจ๋ ํจํด ๋ ํ์ฉํ๊ธฐ
์ผ๋ถ ์ ํ๋ฆฌ์ผ์ด์ ์ย ์ฌ์ฉ์์ ๋ชจ๋ ํ๋์ ๊ธฐ๋กํด๋์๋ค๊ฐ, ์ฑ์ด ์ค๋จ๋๊ฑฐ๋ ์์คํ ์ด ๋ค์ด๋์์ ๋ย ์ด๋ฅผ ๋ค์ ์คํํด ๋ณต๊ตฌํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด๋ ์ปค๋งจ๋ ํจํด์ ํ์ฉํ๋ฉด ํ๋ ํ๋ํ๋๋ฅผย ๊ฐ์ฒด๋ก ์ ์ฅํ๊ณ , ํ์ํ ๋ ๋ค์ย ์คํ (execute())ย ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณต๊ตฌ ์์คํ ์ ๊ตฌํํ๊ธฐ์ ์ ํฉํ๋ค.
์ปค๋งจ๋ ํจํด์ ํ์ฉํ ๋ก๊ทธ ๊ธฐ๋ก ๊ตฌ์กฐ
- ๋ช ๋ น์ ์คํํ ๋๋ง๋ค ํด๋น ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ๋์คํฌ์ ์ ์ฅํ๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋๊ฑฐ๋ ๋ค์ด๋ ํ ์ฌ์์๋๋ฉด,
์ ์ฅ๋ ์ปค๋งจ๋๋ฅผ ๋ค์ ๋ถ๋ฌ์ย execute()๋ฅผ ์์๋๋ก ์คํํ๋ค.
- ์ด ๋ฐฉ์์ผ๋กย ์์คํ ์ ๋ง์ง๋ง ์ฒดํฌํฌ์ธํธ ์ดํ ์ํ๋ก ๋ณต์ํ ์ ์๋ค.
Java์์๋ ์ปค๋งจ๋ ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํํด ์ ์ฅํ ์๋ ์์ง๋ง, ์ง๋ ฌํ๋ ์ ์ฝ์ด ๋ง๊ณ ์ ์ฐ์ฑ์ด ๋จ์ด์ง ์ ์๋ค.
์์ธ: ๋จ์ํ ๋ฆฌ๋ชจ์ปจ์๋ ๋ถํ์ํ ๊ธฐ๋ฅ
- ๋ฆฌ๋ชจ์ปจ ์์ ์ฒ๋ผ ๋จ์ํ ์ํ ์กฐ์๋ง ์๋ ๊ฒฝ์ฐ์ย ๋ก๊ทธ ๊ธฐ๋ก์ด ํฐ ์๋ฏธ๊ฐ ์๋ค.
- ํ์ง๋งย ๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ฑฐ๋,ย ์ค๊ฐ ์ ์ฅ์ด ์ด๋ ค์ด ์ ํ๋ฆฌ์ผ์ด์ ์๋ ๋งค์ฐ ์ ์ฉํ๋ค.
์์: ์คํ๋ ๋์ํธ ์ ํ๋ฆฌ์ผ์ด์
- ๋งค๋ฒ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ์ง ์๊ณ ,
- ํน์ ์ฒดํฌํฌ์ธํธ ์ดํ์ ๋ชจ๋ ์ฌ์ฉ์ ์์ ์ ์ปค๋งจ๋ ๊ฐ์ฒด๋ก ๊ธฐ๋กํ๋ค.
- ๋ณต๊ตฌ ์,ย ๊ธฐ๋ก๋ ์ปค๋งจ๋๋ฅผ ๋ค์ ์คํํ๋ฉด ์ฒดํฌํฌ์ธํธ ์ดํ์ ์ํ๋ฅผ ๋์ด๋ฆด ์ ์๋ค.
ํ์ฅ ๊ฐ๋ฅ์ฑ: ํธ๋์ญ์ ์ ์ฉ
- ๋ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ์ด ๊ตฌ์กฐ๋ฅผย ํธ๋์ญ์
๋จ์๋ก ๋ฌถ์ด,
- ๋ชจ๋ ์์ ์ดย ์์ ํ ์ ์ฉ๋๊ฑฐ๋
- ์ ๋ถ ์ทจ์(rollback)ย ๋๋๋ก ๋ง๋ค ์๋ ์๋ค.
- ์ฆ, ์ปค๋งจ๋ ํจํด์ย ๋ก๊ทธ ์์คํ + ํธ๋์ญ์ ๊ด๋ฆฌย ๊ธฐ๋ฐ์ด ๋ ์ ์๋ค.
๐ฎย ์ค์ ์ ์ฉ! ์ปค๋งจ๋ ํจํด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// ์ปค๋งจ๋ ์ธํฐํ์ด์ค ์ญํ : ์ด๋ฒคํธ ํธ๋ค๋ฌ
interface ActionListener {
actionPerformed(event: Event): void;
}
// ๊ตฌ์ ์ปค๋งจ๋ 1
class AngelListener implements ActionListener {
actionPerformed(event: Event): void {
console.log("ํ์ง๋ง!");
}
}
// ๊ตฌ์ ์ปค๋งจ๋ 2
class DevilListener implements ActionListener {
actionPerformed(event: Event): void {
console.log("ํด!");
}
}
// ํด๋ผ์ด์ธํธ ์ญํ
function SwingObserverEx() {
const button = document.getElementById("actionButton");
if (!button) return;
const angelListener = new AngelListener();
const devilListener = new DevilListener();
// ์ธ๋ณด์ปค ์ญํ : ๋ฒํผ ์ด๋ฒคํธ์ ์ปค๋งจ๋ ๋ฑ๋ก
button.addEventListener("click", (e) => {
angelListener.actionPerformed(e);
devilListener.actionPerformed(e);
});
}
// ์คํ
SwingObserverEx();
Reference
https://velog.io/@toma/ํค๋-ํผ์คํธ-๋์์ธ-ํจํด-6์ฅ-์ปค๋งจ๋-ํจํด-in-Swift
https://velog.io/@ljo_0920/๋์์ธ-ํจํด-์ปค๋งจ๋-ํจํด




