[๋์์ธํจํด] ์ปดํฌ์งํธ ํจํด(Composite Pattern)
ํ๊ทธ: Design Pattern
์นดํ ๊ณ ๋ฆฌ: Design Pattern
์ปดํฌ์งํธ ํจํด(Composite pattern)
์ปดํฌ์งํธ ํจํด์ ๋ํด ์์๋ณด๊ณ , ๋์ ์ ๊ณผ ํ์ ์ฐจ์ด์ ์ ์์๋ด ๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ๊ตฌํ๋ ๋ฉ๋ด ์ถ๋ ฅ ํ๋ก๊ทธ๋จ์ด ์๋ค.
1
2
3
4
5
6
7
[ ๋ฉ์ธ ๋ฉ๋ด ]
1. ๊ณผ์
2. ๊ฒ์๊ธ
3. ํ์
4. ๊ฐ์
์ธ์ฌ
5. ๋์๋ง
0. ์ข
๋ฃ
๋ฉ์ธ ๋ฉ๋ด์์ ํด๋น ๋ฒํธ๋ฅผ ๋๋ฅด๋ฉด ์๋ธ๋ฉ๋ด๊ฐ ์ถ๋ ฅ๋๋ค. ์๋ฅผ๋ค์ด ์ฌ์ฉ์๋ก ๋ถํฐ 2๋ฅผ ์ ๋ ฅ๋ฐ์ ๊ฒ์๊ธ ๋ฉ๋ด๋ก ๋ค์ด๊ฐ๋ฉด ์๋์ ๊ฐ์ ๋ฉ๋ด๊ฐ ์ถ๋ ฅ๋๋ค.
1
2
3
4
5
6
7
[ ๊ฒ์๊ธ ]
1. ๋ฑ๋ก
2. ์กฐํ
3. ๋ณ๊ฒฝ
4. ์ญ์
5. ๋ชฉ๋ก
0. ์ด์
Before
๊ฐ๊ฐ์ ๋ฉ๋ด ํด๋์ค์ ์ ๋ ฅ์ ๋ฐ๋ ์์ค์ฝ๋๊ฐ ์กด์ฌํ๊ณ ๊ทธ ์ ๋ ฅ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ๋ ๊ฐ๊ฐ์ ๋ฉ๋ด ํด๋์ค์ ๊ตฌํ๋์ด ์๋ค.
MainMenu.class
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
public class MainMenu {
...
Menu assignmentMenu = new AssignmentMenu("๊ณผ์ ", this.prompt);
Menu boardMenu = new BoardMenu("๊ฒ์๊ธ", this.prompt);
Menu greetingMenu = new BoardMenu("๊ฐ์
์ธ์ฌ", this.prompt);
Menu memberMenu = new MemberMenu("ํ์", this.prompt);
Menu helpMenu = new HelpMenu("๋์๋ง", this.prompt);
printMenu(); // ๋ฉ์ธ๋ฉ๋ด ์ถ๋ ฅ
while(true) {
String input = this.prompt.input("๋ฉ์ธ> ");
switch (input) {
case "1":
assignmentMenu.execute(prompt);
break;
case "2":
boardMenu.execute(prompt);
break;
case "3":
memberMenu.execute(prompt);
break;
case "4":
greetingMenu.execute(prompt);
break;
case "5":
helpMenu.execute(prompt);
break;
case "0":
System.out.println("์ข
๋ฃํฉ๋๋ค.");
return;
case "menu":
this.printMenu();
break;
default:
System.out.println("๋ฉ๋ด ๋ฒํธ๊ฐ ์ณ์ง ์์ต๋๋ค.");
}
}
}
BoardMenu.class
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
53
54
55
56
57
58
59
60
61
public class BoardMenu {
public void execute(Prompt prompt) {
...
Board[] boards = new Board[3]; // ๊ฒ์๊ธ ์ ์ฅํ ๋ฐฐ์ด
int length = 0; // ํ์ฌ ๊ฒ์๊ธ ์ ์ฅ ์ธ๋ฑ์ค
this.printMenu(); // ์๋ธ๋ฉ๋ด ์ถ๋ ฅ
while (true) {
String input = prompt.input("๋ฉ์ธ/%s> ", this.title);
switch (input) {
case "1":
this.add();
break;
case "2":
this.view();
break;
case "3":
this.modify();
break;
case "4":
this.delete();
break;
case "5":
this.list();
break;
case "0":
return;
case "menu":
this.printMenu();
break;
default:
System.out.println("๋ฉ๋ด ๋ฒํธ๊ฐ ์ณ์ง ์์ต๋๋ค!");
}
}
void add () {
// ๊ฒ์๊ธ ๋ฑ๋ก
}
void list () {
// ๊ฒ์๊ธ ๋ชฉ๋ก
}
void view () {
// ๊ฒ์๊ธ ์์ธ์กฐํ
}
void modify () {
// ๊ฒ์๊ธ ์์
}
void delete () {
// ๊ฒ์๊ธ ์ญ์
}
}
}
์ ์์ค์ฝ๋ ์ฒ๋ผ switch
๋ฌธ์ผ๋ก ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ๊ฐ ๋ฉ๋ด ํด๋์ค๋ง๋ค ์ํํ๊ณ ์๋ค.
์๋ก์ด ๋ฉ๋ด๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค MainMenu
์ ์๋ธ๋ฉ๋ด ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผํ๊ณ case
๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ฌ ์ฝ๋๋ ๋ชจ๋ ์๋ธ๋ฉ๋ด ํด๋์ค๊ฐ ์ค๋ณต ์ฝ๋๋ฅผ ๋ค์ ํฌํจํ๊ณ ์๋ค. (switch ๋ก ์
๋ ฅ์ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ, CRUD ๊ธฐ๋ฅ)
๋ํ ๋ฉ๋ดํด๋์ค๊ฐ ์๋ก ๊ณ์ธต๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์์๋, ์ด๊ฒ์ด ์ฝ๋์์ ์ ํํ์ด ๋์ง ์๋๋ค.
๋ฐ์ดํฐ ๊ทธ ์์ฒด๋ฅผ ํธ๋ค๋ง ํ๋ ์์ค์ฝ๋๋ ์ ์ง๋ณด์ํ๊ธฐ ํ๋ค๊ณ ๊ฐ์ฒด์งํฅ ํจ๋ฌ๋ค์๊ณผ๋ ๋ง์ง ์๋ค. ์ปดํฌ์งํธ ํจํด์ SOLID ๊ฐ์ฒด์งํฅ ์๋ฆฌ ์ค OCP(Open/Closed Principle) ๋ฅผ ๋ง์กฑํ๋ค.
After
๊ธฐ์กด์ switch
๋ก ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅ ๋ฐ์์ ๋ฉ๋ด๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ด ์๋,
๋ฉ๋ด๋ฅผ ์์๋ฉ๋ด ๊ฐ์ฒด
์ ํ์ ๋ฉ๋ด ๊ฐ์ฒด
๋ก ์บก์ํ ํ๊ณ ๊ฐ์ฒด๋ผ๋ฆฌ ์ํธ์์ฉํ๋๋ก ์์ ํ๋ค.
ํด๋
์ ํ์ผ
์ ๊ตฌ์กฐ์ฒ๋ผ ๊ณ์ธต์ ์ธ ํธ๋ฆฌ๊ตฌ์กฐ์ ํ์์ ์ทจํ๋ค.
์ฐ์ Menu
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด MenuGroup
๊ณผ MenuItem
์ ๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ๋ง๋ ๋ค.
MenuGroup
์ ๋ฐ๋ณต์ ์ผ๋ก Menu
๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ฆ, MenuGroup
๋๋ MenuItem
์ ๊ฐ์ง ์ ์๋ค.(add()
๋ก ๋ฐฐ์ด์ ์ถ๊ฐ)
๋ฐ์ดํฐ๋ฅผ ์ด๋ฐ์์ผ๋ก ์กฐ์งํํ๋ค ๋ณด๋ฉด ๋ณตํฉ๊ฐ์ฒด(MenuGroup)๋ฅผ ๋ฐ๋ผ์ ๊ฐ์ง๊ฐ ์ฐ๊ฒฐ๋๋ค๊ฐ ๋ง์ง๋ง์๋ ์(MenuItem)์ผ๋ก ๋๋๋ ํธ๋ฆฌ๊ตฌ์กฐ๊ฐ ๋ง๋ค์ด์ง๋ค.
MenuGroup.class
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
public class MenuGroup implements Menu {
String title;
Menu[] menus = new Menu[10];
int menuSize;
public MenuGroup(String title) {
this.title = title;
}
public void add(Menu menu) {
// menus ๋ฐฐ์ด์ ์๋ธ๋ฉ๋ด๋ฅผ ๋ฃ๋๋ค
}
public void remove(Menu menu) {
// menus ๋ฐฐ์ด์์ ์๋ธ๋ฉ๋ด ์ญ์
}
@Override
public void execute(Prompt prompt) {
this.printMenu();
// ๋ฉ๋ด ๋ฒํธ ์
๋ ฅ ๋ฐ ๋ฉ๋ด ์ถ๋ ฅ
// menus ๋ฐฐ์ด์ ์๋ ์๋ธ๋ฉ๋ด ์คํ(execute)
}
}
๊ธฐ์กด ์์ค์์๋ add()
,remove()
์ ๊ฐ์ด ๋ฉ๋ด๋ฅผ ์ถ๊ฐํ๊ณ ์ญ์ ํ๋ ๊ธฐ๋ฅ์ด ๊ฐ๊ฐ์ ๋ฉ๋ด์ ์กด์ฌํ๋ค.
์ด์ ์๋ก์ด ๋ฉ๋ด๋ฅผ ๋ง๋๋ ์์
์ MenuGroup
์์ ํ๋ค.
MenuGroup
์์ ์๋ธํด๋์ค ์์๋ค์ ๊ด๋ฆฌํ๊ธฐ ์ํ menus
๋ฐฐ์ด์ด ์๊ณ ํด๋น ๋ฐฐ์ด์ ์ถ๊ฐ/์ญ์ ๋ add()
, remove()
๋ฅผ ํตํด์ ํ๋ค.
MenuItem
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
public class MenuItem implements Menu {
String title;
MenuHandler menuHandler;
public MenuItem(String title) {
this.title = title;
}
public MenuItem(String title, MenuHandler menuHandler) {
this(title);
this.menuHandler = menuHandler;
}
@Override
public void execute(Prompt prompt) {
if (this.menuHandler != null) {
this.menuHandler.action();
}
}
@Override
public String getTitle() {
return this.title;
}
์ปดํฌ์งํธ ํจํด์์ leaf ์ ํด๋นํ๋ ๋ถ๋ถ์ด๋ค. leaf ๋ถ๋ถ์ CRUD ์์
์ ๋ํ MenuHandler
๋ฅผ ์ฃผ์
๋ฐ์ ์ฌ์ฉํ๋ค.
์ด๋ ๊ธฐ์กด์ ๋ฉ๋ด ๊ฐ์ฒด์ ์์ฌ์๋ ๋ฉ๋ด ์ถ๋ ฅ
๊ณผ CRUD ๊ธฐ๋ฅ
๋ถ๋ถ์ ๋ถ๋ฆฌ์ํค๊ธฐ ์ํจ์ด๋ค.
Client
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
public class Client {
public static void main(String[] args) {
...
Prompt prompt = new Prompt(System.in);
// new MainMenu(prompt).execute();
BoardRepository boardRepository = new BoardRepository();
MenuGroup mainMenu = new MenuGroup("๋ฉ์ธ");
MenuGroup assignmentMenu = new MenuGroup("๊ณผ์ ");
MenuGroup boardMenu = new MenuGroup("๊ฒ์๊ธ");
MenuGroup memberMenu = new MenuGroup("ํ์");
MenuGroup greetingMenu = new MenuGroup("๊ฐ์
์ธ์ฌ");
MenuGroup helpMenu = new MenuGroup("๋์๋ง");
mainMenu.add(assignmentMenu);
assignmentMenu.add(new MenuItem("๋ฑ๋ก"));
assignmentMenu.add(new MenuItem("์กฐํ"));
assignmentMenu.add(new MenuItem("๋ณ๊ฒฝ"));
assignmentMenu.add(new MenuItem("์ญ์ "));
assignmentMenu.add(new MenuItem("๋ชฉ๋ก"));
mainMenu.add(boardMenu);
boardMenu.add(new MenuItem("๋ฑ๋ก", new BoardAddHandler(boardRepository, prompt)));
boardMenu.add(new MenuItem("์กฐํ", new BoardViewHandler()));
boardMenu.add(new MenuItem("๋ณ๊ฒฝ", new BoardModifyHandler()));
boardMenu.add(new MenuItem("์ญ์ ", new BoardDeleteHandler()));
boardMenu.add(new MenuItem("๋ชฉ๋ก", new BoardListHandler(boardRepository)));
}
}
์ปดํฌ์งํธ ํจํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ ๋จ์ผ ๊ฐ์ฒด์ ๋ณตํฉ ๊ฐ์ฒด ๋ชจ๋ ๋์ผํ๊ฒ ๋ค๋ฃฐ ์ ์๋ค.
๊ธฐ์กด์ new MainMenu(prompt).execute()
๋ก ๊ฐ ๋ฉ๋ด๋ค์ ํธ์ถํ๋ค๋ฉด ์ด์ ๋ ๋ฉ๋ด์ ์ข
์๊ด๊ณ๊ฐ ์ฝ๋์์ ํ์คํ ํํ๋๊ณ , ์ถ๊ฐ/์ญ์ ๋ฅผ ๊ฐํธํ ํ ์ ์๋ค.
๋๊ธ๋จ๊ธฐ๊ธฐ