๋์์ธํจํด
[๋์์ธํจํด] ์ปดํฌ์งํธ(Composite) ํจํด
์์๋๐
2024. 8. 25. 08:37
์ปดํฌ์งํธ ํจํด(Composite Pattern)
- *์ปดํฌ์งํธ ํจํด(Composite Pattern)**์ ๊ตฌ์กฐ์ ๋์์ธ ํจํด ์ค ํ๋๋ก, ๊ฐ์ฒด๋ฅผ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑํ์ฌ ๋ถ๋ถ-์ ์ฒด ๊ณ์ธต์ ํํํ ๋ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํจํด์ ํด๋ผ์ด์ธํธ๊ฐ ๋จ์ผ ๊ฐ์ฒด์ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ค๋ฃฐ ์ ์๋๋ก ํด์ค๋๋ค. ์ฆ, ๊ฐ๋ณ ๊ฐ์ฒด(Leaf)์ ๋ณตํฉ ๊ฐ์ฒด(Composite)๋ฅผ ๋์ผํ ์ธํฐํ์ด์ค๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
1. ์ปดํฌ์งํธ ํจํด์ ๊ธฐ๋ณธ ๊ฐ๋
- ๊ตฌ์ฑ ์์:
- Component: ๊ฐ์ฒด๋ค ๊ฐ์ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ์ ์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ Leaf์ Composite์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ๋ฉ์๋๊ฐ ํฌํจ๋ฉ๋๋ค.
- Leaf: ํธ๋ฆฌ์ ๋ง๋จ ๋ ธ๋๋ฅผ ํํํ๋ฉฐ, ๋ ์ด์ ์์์ ๊ฐ์ง์ง ์๋ ๊ฐ์ฒด์ ๋๋ค. Component ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํฉ๋๋ค.
- Composite: ์์ ๋ ธ๋๋ฅผ ๊ฐ์ง ์ ์๋ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ๋ํ๋ ๋๋ค. Component ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉฐ, ์์ ๋ ธ๋๋ค์ ๊ด๋ฆฌํ๊ณ ์ด๋ค์ ๋ํ ์ฐ์ฐ์ ์์ํฉ๋๋ค.
- ์ฅ์ :
- ํด๋ผ์ด์ธํธ๋ ๊ฐ๋ณ ๊ฐ์ฒด์ ๋ณตํฉ ๊ฐ์ฒด๋ฅผ ๊ตฌ๋ถํ ํ์ ์์ด ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ์ ์ฐํ๊ฒ ํ์ฅํ ์ ์์ผ๋ฉฐ, ์๋ก์ด ์ข ๋ฅ์ ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํ๋๋ผ๋ ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํ ํ์๊ฐ ์์ต๋๋ค.
- ๋จ์ :
- ํธ๋ฆฌ ๊ตฌ์กฐ๊ฐ ๋ณต์กํด์ง ์ ์์ผ๋ฉฐ, ์ ์ฒด ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
- ๋ณตํฉ ๊ฐ์ฒด์ ๊ด๋ฆฌ๋ฅผ ์ํด ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ์ ์๊ฐ์ด ํ์ํ ์ ์์ต๋๋ค.
2. ์ปดํฌ์งํธ ํจํด ์์
์๋ ์์ ์์๋ ํ์ผ ์์คํ ์ ๋ชจ๋ธ๋งํ๋ ๊ตฌ์กฐ๋ฅผ ํตํด ์ปดํฌ์งํธ ํจํด์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค. ์ด ํ์ผ ์์คํ ์์๋ ํ์ผ๊ณผ ๋๋ ํฐ๋ฆฌ๊ฐ ์์ผ๋ฉฐ, ๋๋ ํฐ๋ฆฌ๋ ๋ค๋ฅธ ํ์ผ์ด๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ํฌํจํ ์ ์์ต๋๋ค.
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// Component
class FileSystemComponent {
public:
virtual void showDetails(int indent = 0) const = 0;
virtual ~FileSystemComponent() = default;
};
// Leaf
class File : public FileSystemComponent {
private:
std::string name;
public:
File(const std::string& name) : name(name) {}
void showDetails(int indent = 0) const override {
std::cout << std::string(indent, '-') << name << std::endl;
}
};
// Composite
class Directory : public FileSystemComponent {
private:
std::string name;
std::vector<std::unique_ptr<FileSystemComponent>> children;
public:
Directory(const std::string& name) : name(name) {}
void add(std::unique_ptr<FileSystemComponent> component) {
children.push_back(std::move(component));
}
void showDetails(int indent = 0) const override {
std::cout << std::string(indent, '-') << name << std::endl;
for (const auto& child : children) {
child->showDetails(indent + 2);
}
}
};
int main() {
// ๋ฃจํธ ๋๋ ํฐ๋ฆฌ ์์ฑ
auto root = std::make_unique<Directory>("root");
// ๋ฃจํธ ๋๋ ํฐ๋ฆฌ์ ํ์ผ ์ถ๊ฐ
root->add(std::make_unique<File>("file1.txt"));
root->add(std::make_unique<File>("file2.txt"));
// ์๋ธ ๋๋ ํฐ๋ฆฌ ์์ฑ ๋ฐ ํ์ผ ์ถ๊ฐ
auto subDir = std::make_unique<Directory>("subdir");
subDir->add(std::make_unique<File>("file3.txt"));
subDir->add(std::make_unique<File>("file4.txt"));
// ์๋ธ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ฃจํธ ๋๋ ํฐ๋ฆฌ์ ์ถ๊ฐ
root->add(std::move(subDir));
// ์ ์ฒด ํ์ผ ์์คํ
๊ตฌ์กฐ ์ถ๋ ฅ
root->showDetails();
return 0;
}
3. ์ฝ๋ ์ค๋ช
- Component: FileSystemComponent๋ ํ์ผ๊ณผ ๋๋ ํฐ๋ฆฌ ๋ชจ๋๊ฐ ๊ตฌํํด์ผ ํ๋ ์ธํฐํ์ด์ค๋ก, ์ฌ๊ธฐ์๋ showDetails() ๋ฉ์๋๋ฅผ ์ ์ํ์ต๋๋ค. ์ด ๋ฉ์๋๋ ๊ฐ์ฒด์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ ์ญํ ์ ํฉ๋๋ค.
- Leaf: File ํด๋์ค๋ ๊ฐ๋ณ ํ์ผ์ ๋ํ๋ด๋ฉฐ, showDetails() ๋ฉ์๋๋ฅผ ๊ตฌํํ์ฌ ํ์ผ ์ด๋ฆ์ ์ถ๋ ฅํฉ๋๋ค.
- Composite: Directory ํด๋์ค๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ํ๋ด๋ฉฐ, ๋ค๋ฅธ FileSystemComponent ๊ฐ์ฒด๋ค์ ์์์ผ๋ก ๊ฐ์ง ์ ์์ต๋๋ค. add() ๋ฉ์๋๋ฅผ ํตํด ์์ ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํ๋ฉฐ, showDetails() ๋ฉ์๋๋ฅผ ํตํด ์์๋ค์ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
- Client: main() ํจ์๋ ํ์ผ ์์คํ ์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ฑํ๊ณ , ์ ์ฒด ๊ตฌ์กฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
4. ์คํ ๊ฒฐ๊ณผ
์์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ถ๋ ฅ์ด ๋ํ๋ฉ๋๋ค:
root
--file1.txt
--file2.txt
--subdir
----file3.txt
----file4.txt
์ค๋ช :
- root ๋๋ ํฐ๋ฆฌ ์๋์ file1.txt์ file2.txt ํ์ผ์ด ์๊ณ , subdir๋ผ๋ ์๋ธ ๋๋ ํฐ๋ฆฌ๊ฐ ์กด์ฌํฉ๋๋ค.
- subdir ์๋์๋ file3.txt์ file4.txt ํ์ผ์ด ํฌํจ๋์ด ์์ต๋๋ค.
- ๊ฐ ๋๋ ํฐ๋ฆฌ์ ํ์ผ์ ๊ณ์ธต์ ์ผ๋ก ์ถ๋ ฅ๋ฉ๋๋ค.
์ด ์์ ๋ ์ปดํฌ์งํธ ํจํด์ ์ฌ์ฉํ์ฌ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ํด๋ผ์ด์ธํธ ์ฝ๋์์๋ ๊ฐ๋ณ ๊ฐ์ฒด(ํ์ผ)์ ๋ณตํฉ ๊ฐ์ฒด(๋๋ ํฐ๋ฆฌ)๋ฅผ ๊ตฌ๋ถํ ํ์ ์์ด showDetails() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๊ตฌ์กฐ๋ฅผ ์ถ๋ ฅํ ์ ์์ต๋๋ค.