🎈 컴포지트 패턴 (Composite Pattern)
• 객체들을 계층 구조로 구성하여 개별 객체와 복합 객체를 다룬다.
• 부분-전체 계층을 표현하는 패턴
• 동일한 인터페이스로 일관성을 유지한다.
→ 전체적인 구조 유지에 유용함
• 그래픽 라이브러리, 문서 구조, 조직 구조와 같은 시스템에서 활용된다.
• 디자인 패턴 중 구조 패턴에 해당된다.
[예제 코드] → 컴포지트 패턴 적용
#include <iostream>
#include <vector>
// Component interface
class Graphic {
public:
virtual void draw() = 0;
};
class Circle : public Graphic {
public:
void draw() override {
std::cout << "Circle..." << std::endl;
}
};
class Rectangle : public Graphic {
public:
void draw() override {
std::cout << "Rectangle..." << std::endl;
}
};
// Composite class: Drawing
class Drawing : public Graphic {
public:
void draw() override {
std::cout << "Drawing:" << std::endl;
for (auto shape : shapes) {
shape->draw();
}
}
void addShape(Graphic* shape) {
shapes.push_back(shape);
}
private:
std::vector<Graphic*> shapes;
};
int main() {
Circle circle;
Rectangle rectangle;
Drawing drawing;
drawing.addShape(&circle);
drawing.addShape(&rectangle);
drawing.draw();
return 0;
}
"원(Circle)"과 "사각형(Rectangle)"이 있으며,
기본 요소들을 "도면(Drawing)" 안에 포함할 수 있다
Drawing 클래스는 여러 개의 그래픽 요소를 관리하는데
addShape 함수로 그래픽 요소를 추가한다.
[예제 코드] → 컴포지트 패턴 적용 X
#include <iostream>
#include <vector>
class Shape {
public:
virtual void draw() = 0;
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "그림: 원" << std::endl;
}
};
class Square : public Shape {
public:
void draw() override {
std::cout << "그림: 정사각형" << std::endl;
}
};
int main() {
Circle circle;
Square square;
circle.draw();
square.draw();
return 0;
}
Circle과 Square 클래스가 각각 그리기(draw) 메서드를 갖고 있다.
각 개별객체가 독립적으로 처리된다.
[예제 코드] - 폴더 구조
#include <iostream>
#include <vector>
class FileComponent {
public:
virtual void list() = 0;
};
class File : public FileComponent {
private:
std::string name;
public:
File(std::string name) : name(name) {}
void list() override {
std::cout << "파일: " << name << std::endl;
}
};
// Composite
class Folder : public FileComponent {
private:
std::string name;
std::vector<FileComponent*> children;
public:
Folder(std::string name) : name(name) {}
void add(FileComponent* component) {
children.push_back(component);
}
void list() override {
std::cout << "------------\n폴더: " << name << std::endl;
for (FileComponent* component : children) {
component->list();
}
}
};
int main() {
File* file1 = new File("1");
File* file2 = new File("22");
File* file3 = new File("333");
Folder* root = new Folder("Root");
Folder* folder1 = new Folder("Folder1");
Folder* folder2 = new Folder("Folder2");
folder1->add(file1);
folder1->add(file2);
folder2->add(file3);
root->add(folder1);
root->add(folder2);
root->list();
return 0;
}
폴더(Folder)는 파일(File) 또는 또 다른 폴더를 포함할 수 있다.
폴더 구조는 대표적인 계층 구조인데,
list 메서드와 같이 컴포지트 패턴으로 쉽게 모델링해 볼 수 있다.
🎈 다른 디자인 패턴과 비교
데코레이터 패턴은 객체 동작을 동적으로 확장하거나 변경하기 위한 패턴으로
객체를 래핑하여 새로운 행동을 추가한다.
컴포지트 패턴은 여러 객체를 복합 객체로 다루는 것에서 차이를 보인다.
어댑터 패턴은 서로 다른 인터페이스를 갖는 클래스 함께 사용하기 위한 패턴
한 클래스의 인터페이스를 다른 클래스가 사용할 수 있도록 변환한다.
중재자 패턴은 객체간의 상호 작용을 중재하고 캡슐화하는 패턴입
객체들이 직접 통신하지 않고 중재자를 통해 상호 작용
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] 퍼사드 패턴 (Facade Pattern) (54) | 2023.11.09 |
---|---|
[디자인 패턴] 관찰자(Observer) 패턴 (4) | 2023.11.06 |
[디자인패턴] 인터프리터 패턴 (Interpreter Pattern) (2) | 2023.11.04 |
[디자인패턴] 커맨드 패턴 (Command Pattern) (1) | 2023.11.03 |
[디자인패턴] 어댑터 패턴 (Adapter Pattern) (1) | 2023.11.02 |
댓글