๐ ๋ณตํฉ์ฒด(Composite) ํจํด - ์๋ฒฝ ๋ง์คํฐํ๊ธฐ
Composite Pattern
๋ณตํฉ์ฒด ํจํด(Composite Pattern)์ ๋ณตํฉ ๊ฐ์ฒด(Composite) ์ ๋จ์ผ ๊ฐ์ฒด(Leaf)๋ฅผ ๋์ผํ ์ปดํฌ๋ํธ๋ก ์ทจ๊ธํ์ฌ, ํด๋ผ์ด์ธํธ์๊ฒ ์ด ๋์ ๊ตฌ๋ถํ์ง ์๊ณ ๋์ผํ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋๋ก ํ๋ ๊ตฌ์กฐ ํจํด์ด๋ค.
๋ณตํฉ์ฒด ํจํด์ ์ ์ฒด-๋ถ๋ถ์ ๊ด๊ณ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด๋ค ์ฌ์ด์ ๊ด๊ณ๋ฅผ ํธ๋ฆฌ ๊ณ์ธต ๊ตฌ์กฐ๋ก ์ ์ํด์ผ ํ ๋ ์ ์ฉํ๋ค. ์๋์ฐ๋ ๋ฆฌ๋ ์ค์ ํ์ผ ์์คํ ๊ตฌ์กฐ๋ฅผ ๋ ์ฌ๋ ค๋ณด๋ฉด ์ฝ๊ฒ ์ดํดํ ์ ์๋ค.
ํด๋(๋๋ ํ ๋ฆฌ) ์์๋ ํ์ผ์ด ๋ค์ด ์์์๋ ์๊ณ ํ์ผ์ ๋ด์ ๋ ๋ค๋ฅธ ํด๋๋ ๋ค์ด์์ ์ ์๋ค. ์ด๋ฅผ ๋ณตํฉ์ ์ผ๋ก ๋ด์์ ์๋ค ํด์ Composite ๊ฐ์ฒด๋ผ๊ณ ๋ถ๋ฆฌ์ด๋ค. ๋ฐ๋ฉด ํ์ผ์ ๋จ์ผ ๊ฐ์ฒด ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ Leaf ๊ฐ์ฒด๋ผ๊ณ ๋ถ๋ฆฌ์ด๋ค. ์ฆ Leaf๋ ์์์ด ์๋ค.
๋ณตํฉ์ฒด ํจํด์ ๋ฐ๋ก ์ด ํด๋์ ํ์ผ์ ๋์ผํ ํ์ ์ผ๋ก ์ทจ๊ธํ์ฌ ๊ตฌํ์ ๋จ์ํ ์ํค๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ค. ํด๋ ์์๋ ํ์ผ ๋ฟ๋ง ์๋๋ผ ์๋ธ ํด๋๊ฐ ์ฌ์ ์๊ณ ๋ ์๋ธ ํด๋์์ ์๋ธ ํด๋๊ฐ ์ค๊ณ .. ์ด๋ฐ์์ผ๋ก ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ๋ค ๋ณด๋ฉด, ์์นซ ๋ณต์กํด ์ง ์ ๋ ์๋ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ฌ๊ท ๋์์ ํตํด ํ์ ๊ฐ์ฒด๋ค์๊ฒ ์์ ์ ์์ํ๋ค. ๊ทธ๋ฌ๋ฉด ๋ณตํฉ ๊ฐ์ฒด์ ๋จ์ผ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ๋๊ฐ์ ์์ ์ ์ ์ฉํ ์ ์์ด ๋จ์ผ / ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถํ ํ์๊ฐ ๊ฑฐ์ ์์ด์ง๋ค.
์๋์ฐ์์ ํด๋์ ํ์ผ์ ์์ฐํ ๋ค๋ฅธ ๋์ด์ง๋ง, ๋ฆฌ๋ ์ค(Unix)์์ ๋๋ ํ ๋ฆฌ์ ํ์ผ์ ๋ชจ๋ ํ์ผ๋ก ์ทจ๊ธ๋๋ค. ์ด์ฐ๋ณด๋ฉด ๋ฆฌ๋ ์ค OS๊ฐ ๋ณตํฉ์ฒด(Composite) ํจํด์ ํตํด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ์๋ค๊ณ ๋ณผ ์ ์๋ค.
๋น์ฐํ ์ค์ ์ค๊ณ๋ ๋ค๋ฅด๊ฒ ์ง๋ง, ๋ณตํฉ์ฒด ํจํด์ ์ ๋ฌธํ๊ธฐ ์ด๋ ค์ด ํจํด์ค ํ๋์ด๊ธฐ์ ์ด๋ฌํ ๋น์ ๋ฅผ ํตํด ์ข๋ ํจํด์ ์น์ํ๊ฒ ์ ๊ทผํ๋๋ก ํด๋ณด์.
์ ๋ฆฌํ์๋ฉด, Composite ํจํด์ ๊ทธ๋ฆ๊ณผ ๋ด์ฉ๋ฌผ์ ๋์ผ์ํด์ ์ฌ๊ท์ ์ธ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๋์์ธ ํจํด์ด๋ผ๊ณ ๋งํ ์ ์๋ค.
Composite ํจํด ๊ตฌ์กฐ
- Component : Leaf์ Compsite ๋ฅผ ๋ฌถ๋ ๊ณตํต์ ์ธ ์์ ์ธํฐํ์ด์ค
- Composite : ๋ณตํฉ ๊ฐ์ฒด๋ก์, Leaf ์ญํ ์ด๋ Composite ์ญํ ์ ๋ฃ์ด ๊ด๋ฆฌํ๋ ์ญํ ์ ํ๋ค.
- Component ๊ตฌํ์ฒด๋ค์ ๋ด๋ถ ๋ฆฌ์คํธ๋ก ๊ด๋ฆฌํ๋ค
- add ์ remove ๋ฉ์๋๋ ๋ด๋ถ ๋ฆฌ์คํธ์ ๋จ์ผ / ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ ์ฅ
- Component ์ธํฐํ์ด์ค์ ๊ตฌํ ๋ฉ์๋์ธ operation์ ๋ณตํฉ ๊ฐ์ฒด์์ ํธ์ถ๋๋ฉด ์ฌ๊ท ํ์ฌ, ์ถ๊ฐ ๋จ์ผ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ ํ์ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ์ํํ๊ฒ ๋๋ค.
- Leaf: ๋จ์ผ ๊ฐ์ฒด๋ก์, ๋จ์ํ๊ฒ ๋ด์ฉ๋ฌผ์ ํ์ํ๋ ์ญํ ์ ํ๋ค.
- Component ์ธํฐํ์ด์ค์ ๊ตฌํ ๋ฉ์๋์ธ operation์ ๋จ์ผ ๊ฐ์ฒด์์ ํธ์ถ๋๋ฉด ์ ์ ํ ๊ฐ๋ง ๋ฐํํ๋ค
- Client : ํด๋ผ์ด์ธํธ๋ Component๋ฅผ ์ฐธ์กฐํ์ฌ ๋จ์ผ / ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ํ๋์ ๊ฐ์ฒด๋ก์ ๋ค๋ฃฌ๋ค.
๋ณตํฉ์ฒด ํจํด์ ํต์ฌ์ Composite ์ Leaf๊ฐ ๋์์ ๊ตฌํํ๋ operation() ์ธํฐํ์ด์ค ์ถ์ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ , Composite ๊ฐ์ฒด์ operation() ๋ฉ์๋๋ ์๊ธฐ ์์ ์ ํธ์ถํ๋ ์ฌ๊ท ํํ๋ก ๊ตฌํํ๋ ๊ฒ์ด๋ค. ์๋ํ๋ฉด ํด๋ ์์ ํด๋๋ฅผ ๋ฃ๊ณ , ๊ทธ ์์ ๋ ํด๋๋ฅผ ๋ฃ๊ณ ํ์ผ์ ๋ฃ๋ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์๊ฐํด๋ณด๋ฉด, ์ฌ๊ท์ ์ผ๋ก ๋ฐ๋ณต๋๋ ํ์์ด ๋ํ๋๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ๋จ์ผ์ฒด์ ๋ณตํฉ์ฒด๋ฅผ ๋์ผํ ๊ฐ์ฒด๋ก ์ทจ๊ธํ์ฌ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ๊ท ํจ์ ์๋ฆฌ๋ฅผ ์ด์ฉํ๋ค.
Composite ํจํด ํ๋ฆ
ํด๋์ค ๊ตฌ์ฑ
interface Component {
void operation();
}
class Leaf implements Component {
@Override
public void operation() {
System.out.println(this + " ํธ์ถ");
}
}
class Composite implements Component {
// Leaf ์ Composite ๊ฐ์ฒด ๋ชจ๋๋ฅผ ์ ์ฅํ์ฌ ๊ด๋ฆฌํ๋ ๋ด๋ถ ๋ฆฌ์คํธ
List<Component> components = new ArrayList<>();
public void add(Component c) {
components.add(c); // ๋ฆฌ์คํธ ์ถ๊ฐ
}
public void remove(Component c) {
components.remove(c); // ๋ฆฌ์คํธ ์ญ์
}
@Override
public void operation() {
System.out.println(this + " ํธ์ถ");
// ๋ด๋ถ ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ, ๋จ์ผ Leaf์ด๋ฉด ๊ฐ์ ์ถ๋ ฅํ๊ณ ,
// ๋๋ค๋ฅธ ์๋ธ ๋ณตํฉ ๊ฐ์ฒด์ด๋ฉด, ๋ค์ ๊ทธ ๋ด๋ถ๋ฅผ ์ํํ๋ ์ฌ๊ท ํจ์ ๋์์ด ๋๋ค.
for (Component component : components) {
component.operation(); // ์๊ธฐ ์์ ์ ํธ์ถ(์ฌ๊ท)
}
}
public List<Component> getChild() {
return components;
}
}
ํด๋์ค ํ๋ฆ
class Client {
public static void main(String[] args) {
// 1. ์ต์์ ๋ณตํฉ์ฒด ์์ฑ
Composite composite1 = new Composite();
// 2. ์ต์์ ๋ณตํฉ์ฒด์ ์ ์ฅํ Leaf์ ๋๋ค๋ฅธ ์๋ธ ๋ณตํฉ์ฒด ์์ฑ
Leaf leaf1 = new Leaf();
Composite composite2 = new Composite();
// 3. ์ต์์ ๋ณตํฉ์ฒด์ ๊ฐ์ฒด๋ค์ ๋ฑ๋ก
composite1.add(leaf1);
composite1.add(composite2);
// 4. ์๋ธ ๋ณตํฉ์ฒด์ ์ ์ฅํ Leaf ์์ฑ
Leaf leaf2 = new Leaf();
Leaf leaf3 = new Leaf();
Leaf leaf4 = new Leaf();
// 5. ์๋ธ ๋ณตํฉ์ฒด์ ๊ฐ์ฒด๋ค์ ๋ฑ๋ก
composite2.add(leaf2);
composite2.add(leaf3);
composite2.add(leaf4);
// 6. ์ต์์ ๋ณตํฉ์ฒด์ ๋ชจ๋ ์์ ๋
ธ๋๋ค์ ์ถ๋ ฅ
composite1.operation();
}
}
ํด๋ผ์ด์ธํธ์์ operation ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด, ๋จ์ผ์ฒด์ผ ๊ฒฝ์ฐ ๊ฐ์ด ํธ์ถ ๋๊ณ , ๋ณตํฉ์ฒด์ผ ๊ฒฝ์ฐ ์๊ธฐ ์์ ์ ํธ์ถํ๋ ์ฌ๊ท ํจ์์ ์ํด ์ ์ฅํ๊ณ ์๋ ํ์ Leaf ๊ฐ์ฒด๋ค์ ์ํํ์ฌ ํธ์ถํ๊ฒ ๋๋ค.
Composite ํจํด ํน์ง
ํจํด ์ฌ์ฉ ์๊ธฐ
- ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ๋ ๊ณ์ธต์ ํธ๋ฆฌ ํํ์ ๋ค๋ฃจ์ด์ผ ํ ๋
- ๋ณต์กํ๊ณ ๋ํดํ ๋จ์ผ / ๋ณตํฉ ๊ฐ์ฒด ๊ด๊ณ๋ฅผ ๊ฐํธํ ๋จ์ํํ์ฌ ๊ท ์ผํ๊ฒ ์ฒ๋ฆฌํ๊ณ ์ถ์๋
ํจํด ์ฅ์
- ๋จ์ผ์ฒด์ ๋ณตํฉ์ฒด๋ฅผ ๋์ผํ๊ฒ ์ฌ๊ธฐ๊ธฐ ๋๋ฌธ์ ๋ฌถ์ด์ ์ฐ์ฐํ๊ฑฐ๋ ๊ด๋ฆฌํ ๋ ํธ๋ฆฌํ๋ค.
- ๋คํ์ฑ ์ฌ๊ท๋ฅผ ํตํด ๋ณต์กํ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ค ํธ๋ฆฌํ๊ฒ ๊ตฌ์ฑ ํ ์ ์๋ค.
- ์ํ์ , ์์ง์ ๋ชจ๋ ๋ฐฉํฅ์ผ๋ก ๊ฐ์ฒด๋ฅผ ํ์ฅํ ์ ์๋ค.
- ์๋ก์ด Leaf ํด๋์ค๋ฅผ ์ถ๊ฐํ๋๋ผ๋ ํด๋ผ์ด์ธํธ๋ ์ถ์ํ๋ ์ธํฐํ์ด์ค ๋ง์ ๋ฐ๋ผ๋ณด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐฉ ํ์ ์์น(OCP)์ ์ค์ ํ๋ค. (๋จ์ผ ๋ถ๋ถ์ ํ์ฅ์ด ์ฉ์ด)
ํจํด ๋จ์
- ์ฌ๊ท ํธ์ถ ํน์ง ์ ํธ๋ฆฌ์ ๊น์ด(depth)๊ฐ ๊น์ด์ง ์๋ก ๋๋ฒ๊น ์ ์ด๋ ค์์ด ์๊ธด๋ค.
- ์ค๊ณ๊ฐ ์ง๋์น๊ฒ ๋ฒ์ฉ์ฑ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ์๋ก์ด ์์๋ฅผ ์ถ๊ฐํ ๋ ๋ณตํฉ ๊ฐ์ฒด์์ ๊ตฌ์ฑ ์์์ ์ ์ฝ์ ๊ฐ๊ธฐ ํ๋ค๋ค.
- ์๋ฅผ๋ค์ด, ๊ณ์ธตํ ๊ตฌ์กฐ์์ leaf ๊ฐ์ฒด์ composite ๊ฐ์ฒด๋ค์ ๋ชจ๋ ๋์ผํ ์ธํฐํ์ด์ค๋ก ๋ค๋ฃจ์ด์ผํ๋๋ฐ, ์ด ๊ณตํต ์ธํฐํ์ด์ค ์ค๊ณ๊ฐ ๊น๋ค๋ก์ธ ์ ์๋ค.
- ๋ณตํฉ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๋ ๋ถ๋ถ ๊ฐ์ฒด์ ์ข ๋ฅ๋ฅผ ์ ํํ ํ์๊ฐ ์์ ๋
- ์ํ์ ๋ฐฉํฅ์ผ๋ก๋ง ํ์ฅ์ด ๊ฐ๋ฅํ๋๋ก Leaf๋ฅผ ์ ํํ๋ Composite๋ฅผ ๋ง๋ค๋
์์ ๋ฅผ ํตํด ์์๋ณด๋ Composite ํจํด
์์ดํ ์ ๋ด๋ ๊ฐ๋ฐฉ์ ๋ด์ ๊ฐ๋ฐฉ
๋ณตํฉ(composite) ๊ฐ์ฒด์ ๋จ์ผ(leaf) ๊ฐ์ฒด๋ฅผ ์์์ ์์ดํ ์ผ๋ก ๋น์ ํ์๋ฉด ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ํํํ ์ ์์ ๊ฒ์ด๋ค. ์์ ์์ ์์ดํ ์ ๋ฃ๊ณ , ๋ค์ ๊ทธ ์์๋ฅผ ์์ ์์ ๋ฃ๋ ์์ผ๋ก ๋ง์ด๋ค.
์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ๋ณด๋ค ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ๊ฒ ์ปดํฌ์งํธ ํจํด์ ํตํด ๊ตฌํํด๋ณด์.
๋ค์ Item ํด๋์ค์ ๊ทธ๋ฅผ ๋ด๋ Bag ํด๋์ค๊ฐ ์๋ค๊ณ ํ์. ๊ฐ๋ฐฉ์์ ์์ดํ ์ ๋ด๋ ํ์์ด๋, Item ํด๋์ค๋ Leaf๊ฐ ๋๊ณ Bag ํด๋์ค๋ Composite๊ฐ ๋๋ค.
์๋ ์ฝ๋์์ ์ฐ๋ฆฌ๊ฐ ๊ตฌํํ๊ณ ์ถ์ ๊ฒ์ Bag ์ ๋ฆฌ์คํธ์ ๋ด๊ฒจ์ง Item ๊ฐ์ฒด๋ค์ ์ด ๊ฐ๊ฒฉ(price) ๊ฐ์ ์ถ์ถํ๊ณ ์ถ๋ค๊ณ ํ๋ค. ๊ทธ๋ฐ๋ฐ ๋จ์ํ ๊ฐ๋ฐฉ ์์ ์์ดํ ๋ค์ด ๋ค์ด์์ ๋ฟ ์๋๋ผ ๋ณต์์ ์์ดํ ์ ๋ด์ ๋๋ค๋ฅธ ๊ฐ๋ฐฉ๋ค์ด ์ฌ๋ฌ๊ฐ ๋ค์ด ์์ ์ ์๊ณ ๊ทธ ๊ฐ๋ฐฉ์์ ๊ฐ๋ฐฉ์ด ๋ค์ด์์ ์ ์๋ค. ๊ทธ๋ ๋ค๋ฉด ๋ฃจํธ ๊ฐ๋ฐฉ์ผ ๊ฒฝ์ฐ ํ์ ๊ณ์ธต๊น์ง ์ํํ์ฌ ์์ดํ ์ price๊ฐ์ ํฉ์ฐํด์ผ ๋๋๋ฐ ์ด๋ฌํ ๊ณ์ธต ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ปดํฌ์งํธ ํจํด์ผ๋ก ํด๋์ค๋ฅผ ๊ตฌ์ฑ์ ํ๋ฉด ์๋์ ๊ฐ์ด ๋๊ฒ ๋๋ค.
- Composite์ Leaf ๊ฐ์ฒด๋ฅผ ๊ณต์ฉ์ผ๋ก ๋ฌถ๋ ItemComponent ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ , Composite์ Leaf ๊ฐ์ฒด์์ ๋์์ ์ฐ์ด๋ ์ถ์ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
- Composite ๊ฐ์ฒด์ธ Bag ํด๋์ค์์ ItemComponent ํ์ ์ ๊ณต์ฉ ์์ดํ ์ ๋ด๋ ๋ด๋ถ ๋ฆฌ์คํธ๋ฅผ ์ ์ํ๋ค.
- Component ์ธํฐํ์ด์ค์ ๊ณตํต์ ์ธ operation์ธ
getPrice()๋ฉ์๋๋ Item์ผ ๊ฒฝ์ฐ ๊ทธ๋๋ก price๊ฐ์ ๋ฐํํ๋ฉด ๋์ง๋ง, Bag์ผ ๊ฒฝ์ฐ ๊ฐ๋ฐฉ์ ๋จ์ํ ์์ดํ ์ ๋ด๋ ๊ทธ๋ฆ์ผ ๋ฟ์ด๊ธฐ ๋๋ฌธ์ ์๊ธฐ ์์ ์ ํธ์ถํ์ฌ ํ์ฌ ๊ฐ๋ฐฉ์ ๋ค์ด์๋ Item์ ์ํํ๋ ์ฌ๊ท ๋์์ ํํ๊ฒ ๋๋ค.
// Component ์ธํฐํ์ด์ค
interface ItemComponent {
int getPrice();
String getName();
}
// Composite ๊ฐ์ฒด
class Bag implements ItemComponent {
// ์์ดํ
๋ค๊ณผ ์๋ธ ๊ฐ๋ฐฉ ๋ชจ๋๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์ธํฐํ์ด์ค ํ์
๋ฆฌ์คํธ๋ก ๊ด๋ฆฌ
List<ItemComponent> components = new ArrayList<>();
String name; // ๊ฐ๋ฐฉ ์ด๋ฆ
public Bag(String name) {
this.name = name;
}
// ๋ฆฌ์คํธ์ ์์ดํ
& ๊ฐ๋ฐฉ ์ถ๊ฐ
public void add(ItemComponent item) {
components.add(item);
}
// ํ์ฌ ๊ฐ๋ฐฉ์ ๋ด์ฉ๋ฌผ์ ๋ฐํ
public List<ItemComponent> getComponents() {
return components;
}
@Override
public int getPrice() {
int sum = 0;
for (ItemComponent component : components) {
// ๋ง์ผ ๋ฆฌ์คํธ์์ ๊ฐ์ ธ์จ ์์๊ฐ Item์ด๋ฉด ์ ์๊ฐ์ ๋ฐ์ ๊ฒ์ด๊ณ , Bag์ด๋ฉด '์ฌ๊ท ํจ์' ๋์์ด ๋๊ฒ ๋๋ค โ
sum += component.getPrice(); // ์๊ธฐ ์์ ํธ์ถ(์ฌ๊ท)
}
return sum; // ๊ทธ๋ ๊ฒ ์ฌ๊ท์ ์ผ๋ก ๋์ ํ์ ์์ดํ
๋ค์ ๊ฐ์ ๋ํ๊ณ ๋ฐํํ๊ฒ ๋๋ค.
}
@Override
public String getName() {
return name;
}
}
// Leaf ๊ฐ์ฒด
class Item implements ItemComponent {
String name; // ์์ดํ
์ด๋ฆ
int price; // ์์ดํ
๊ฐ๊ฒฉ
public Item(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public int getPrice() {
return price;
}
@Override
public String getName() {
return name;
}
}
class Client {
public static void main(String[] args) {
// 1. ๋ฉ์ธ ๊ฐ๋ฐฉ ์ธ์คํด์ค ์์ฑ
Bag bag_main = new Bag("๋ฉ์ธ ๊ฐ๋ฐฉ");
// 2. ์์ดํ
์ธ์คํด์ค ์์ฑ
Item armor = new Item("๊ฐ์ท", 250);
Item sword = new Item("์ฅ๊ฒ", 500);
// 3. ๋ฉ์ธ ๊ฐ๋ฐฉ์๋ ๋ชจํ์ ํ์ํ ๋ฌด๊ตฌ ์์ดํ
๋ง์ ์ถ๊ฐ
bag_main.add(armor);
bag_main.add(sword);
// 4. ์๋ธ ๊ฐ๋ฐฉ ์ธ์คํด์ค ์์ฑ
Bag bag_food = new Bag("์์ ๊ฐ๋ฐฉ");
// 5. ์์ดํ
์ธ์คํด์ค ์์ฑ
Item apple = new Item("์ฌ๊ณผ", 400);
Item banana = new Item("๋ฐ๋๋", 130);
// 6. ์๋ธ ๊ฐ๋ฐฉ์๋ ์์ ์์ดํ
๋ง์ ์ถ๊ฐ
bag_food.add(apple);
bag_food.add(banana);
// 7. ์๋ธ ๊ฐ๋ฐฉ์ ๋ฉ์ธ ๊ฐ๋ฐฉ์ ๋ฃ์
bag_main.add(bag_food);
// ----------------------------------------------------- //
Client client = new Client();
// ๊ฐ๋ฐฉ ์์ ์๋ ๋ชจ๋ ์์ดํ
์ ์ด ๊ฐ์ด์น๋ฅผ ์ถ๋ ฅ (๊ฐ๋ฐฉ์์ ์์ดํ
๋ฟ๋ง ์๋๋ผ ์๋ธ ๊ฐ๋ฐฉ๋ ๋ค์ด์์)
client.printPrice(bag_main);
// ์๋ธ ๊ฐ๋ฐฉ ์์ ์๋ ๋ชจ๋ ์์ดํ
์ ์ด ๊ฐ์ด์น๋ฅผ ์ถ๋ ฅ
client.printPrice(bag_food);
}
public void printPrice(ItemComponent bag) {
int result = bag.getPrice();
System.out.println(bag.getName() + "์ ์์ดํ
์ดํฉ : " + result + " ๊ณจ๋");
}
}
ํด๋ผ์ด์ธํธ์์๋ ItemComponent ๋ง์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ Item, Bag ๊ตฌํ์ฒด ์๊ด ์์ด(์ ์ฒด, ๊ฐ๋ณ ๊ตฌ๋ถ ์์ด) ๊ตฌํ ๋ฉ์๋๋ง ํธ์ถํ๋ฉด ๋ด๋ถ์์ ์ ์๋ ๊ตฌํ์ ๋ฐ๋ผ ์ํ๋ ๊ฐ์ ์ป์ ์ ์๊ฒ ๋๋ค.
๋ง์ผ ํจํด์ ์ฌ์ฉํ์ง ๊ณ์ธต ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๋งค์ฐ ํ๋ํ ์ฝ๋ฉ์ ํด์ผ ํ ์ง๋ ๋ชจ๋ฅธ๋ค.
ํ์ผ ๋๋ ํ ๋ฆฌ ์์คํ ๊ตฌํ
๋ณธ ํฌ์คํ
์ด๋ฐ์ ์์๋ฅผ ๋ค์๋ ํ์ผ-ํด๋ ์์คํ
์ ๊ตฌํํด๋ณด์. ์๋ฅผ๋ค์ด ๋ฆฌ๋
์ค์์ ls ๋ tree ๋ช
๋ น์ด๋ฅผ ์ฐ๋ฉด ํ์ผ๋ค์ด ์ผ๊ด์ ์ผ๋ก ์ถ๋ ฅ๋๋๋ฐ ์ด ๊ธฐ๋ฅ์ ๋น์ทํ๊ฒ ์ปดํฌ์งํธ ํจํด์ ํตํด ๊ตฌ์ฑํด๋ณด๊ณ ์ ํ๋ค. ์์์ ํ๋ฒ ์ฐ์ตํ๋ ๊ฐ๋ฐฉ-์์ดํ
๊ตฌ์กฐ๋ฅผ ํด๋-ํ์ผ ๊ตฌ์กฐ๋ก ๊ทธ๋๋ก ์นํ๋ง ํ๋ฉด ๋๋ค.
// Component
interface Node {
// ๊ณ์ธต ํธ๋ฆฌ ์ถ๋ ฅ
void print();
void print(String str);
// ํ์ผ/ํด๋ ์ฉ๋ ์ป๊ธฐ
int getSize();
}
// Composite
class Folder implements Node {
private String name; // ํด๋ ์ด๋ฆ
private ArrayList<Node> list;
public Folder(String name) {
this.name = name;
list = new ArrayList<>();
}
// ๋ฆฌ์คํธ์ ํด๋, ํ์ผ ์ถ๊ฐ
public void add(Node node) {
list.add(node);
}
// ๊ณต๋ฐฑ indent ํํ ์ฒ๋ฆฌ๋ฅผ ์ํ print ๋ฉ์๋ ์ค๋ฒ๋ก๋ฉ
public void print() {
this.print("");
}
public void print(String str) {
int size = getSize(); // ํด๋๊ฐ ๋ด๊ณ ์๋ ๋ชจ๋ ํ์ผ์ ๋ํ ์ฉ๋ ํฉ์ฐ
System.out.println(str + "\uD83D\uDCC2" + name + " (" + size + "kb)");
for (Node node : list) {
// Folder ์ผ ๊ฒฝ์ฐ ์ฌ๊ท ๋์
node.print(str + " "); // ์ธ์๋ก ๊ณต๋ฐฑ๋ฌธ์๋ฅผ ํ ๋นํ์ฌ indent ์ฒ๋ฆฌ
}
}
// ๊ฐ ํ์ผ์ ์ฉ๋(kb) ๊ตฌํ๊ธฐ
public int getSize() {
int sum = 0;
for (Node node : list) {
sum += node.getSize(); // print ๋ก์ง๊ณผ ๋๊ฐ์ด ์ฌ๊ท ๋์
}
return sum;
}
}
// Leaf
class File implements Node {
private String name; // ํ์ผ ์ด๋ฆ
private int size; // ํ์ผ ์ฌ์ด์ฆ
public File(String name, int size) {
this.name = name;
this.size = size;
}
public void print() {
this.print("");
}
public void print(String str) {
System.out.println(str + "\uD83D\uDCDC" + name + " (" + size + "kb)");
}
public int getSize() {
return size;
}
}
class Client {
public static void main(String[] args) {
Folder root = new Folder("root");
File file1 = new File("file1", 10);
Folder sub1 = new Folder("sub1");
Folder sub2 = new Folder("sub2");
root.add(sub1);
root.add(file1);
root.add(sub2);
File file11 = new File("file11", 10);
File file12 = new File("file12", 10);
sub1.add(file11);
sub1.add(file12);
File file21 = new File("file21", 10);
sub2.add(file21);
// ์ ์ฒด dir ์ถ๋ ฅ
root.print();
}
}
ํด๋ผ์ด์ธํธ์์ ํด๋๋ ํ์ผ์ด๋ ๋ ธ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๋ณตํฉ์ฒด์ธ ํด๋์ ์ถ๊ฐ๋ง ํด์ฃผ๋ฉด ์์์ ๊ณ์ธต ๊ตฌ์กฐ๊ฐ ํ์ฑ๋๊ฒ ๋๊ณ , ์ด๋ฅผ ์ํํ ๋ ์ฌ๊ท ๋์์ ํตํด ๋ชจ๋ ๋ ธ๋๋ค์ ์ ๊ทผํ๊ฒ ๋๋ค.
์ฐธ๊ณ ๋ก print ๋ฉ์๋๋ฅผ ๋๊ฐ๋ก ์ค๋ฒ๋ก๋ฉ(overloading) ํ๊ฒ ์ด์ํ ์๋ ์์ง๋ง, ๊ณต๋ฐฑ indent๋ฅผ ํํํ๊ธฐ ์ํ ๊ธฐ๋ฒ ์ค ํ๋์ด๋ค. ๋ฌธ์์ด ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง print ๋ฉ์๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ์ฌ ๊ณต๋ฐฑ์ ์ถ๊ฐํ๋ ์์ด๋ค.
# ์ฐธ๊ณ ์๋ฃ
์ฝ๋ฉ์ผ๋ก ํ์ตํ๋ GoF์ ๋์์ธ ํจํด - ๋ฐฑ๊ธฐ์
https://www.youtube.com/watch?v=g96bJvVDZPs
https://refactoring.guru/design-patterns/composite
https://stacktraceguru.com/composite-design-pattern/
http://www-sop.inria.fr/axis/cbrtools/usermanual-eng/Patterns/Composite.html
https://springframework.guru/gang-of-four-design-patterns/composite-pattern/