介紹
? ? ? ? 組合模式組合多個對象形成樹形結構以表示具有“部分-整體”關系的層次結構。組合模式對單個對象(即葉子對象)和組合對象(即容器對象)的使用具有一致性,又可以稱為“部分—整體”(Part-Whole)模式,它是一種對象結構型模式。
實現(xiàn)
myclass.h文章來源:http://www.zghlxwxcb.cn/news/detail-806134.html
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <vector>
class Component { // 抽象基類
public:
virtual void operation();
virtual void add(Component *component);
virtual void remove(Component *component);
virtual Component *getChild(int i);
protected:
std::string m_name;
};
class LeafComponent : public Component { // 葉子節(jié)點具體類
public:
LeafComponent(const std::string &name);
void operation() override;
};
class CompositeComponent : public Component { // 容器節(jié)點具體類
public:
CompositeComponent(const std::string &name);
void operation() override;
void add(Component *component) override;
void remove(Component *component) override;
Component *getChild(int i) override;
private:
std::vector<Component *> m_components;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
void Component::operation() {
throw std::runtime_error("operation exception");
}
void Component::add(Component *component) {
throw std::runtime_error("add exception");
}
void Component::remove(Component *component) {
throw std::runtime_error("remove exception");
}
Component *Component::getChild(int i) {
throw std::runtime_error("getChild exception");
}
LeafComponent::LeafComponent(const std::string &name) {
m_name = name;
}
void LeafComponent::operation() {
std::cout << m_name << ": LeafComponent::operation()" << std::endl;
}
CompositeComponent::CompositeComponent(const std::string &name) {
m_name = name;
}
void CompositeComponent::operation() {
std::cout << m_name << ": CompositeComponent::operation()" << std::endl;
for (auto it = m_components.begin(); it != m_components.end(); ++it) {
(*it)->operation();
}
}
void CompositeComponent::add(Component *component) {
m_components.push_back(component);
}
void CompositeComponent::remove(Component *component) {
for (auto it = m_components.begin(); it != m_components.end(); ++it) {
if (*it == component) {
m_components.erase(it);
break;
}
}
}
Component *CompositeComponent::getChild(int i) {
if (i < m_components.size()) {
return m_components[i];
} else {
return nullptr;
}
}
main.cpp
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Component *leaf = new LeafComponent("leaf1");
Component *composite = new CompositeComponent("composite1");
Component *composite2 = new CompositeComponent("composite2");
composite->add(new LeafComponent("leaf2"));
composite->add(new LeafComponent("leaf3"));
composite2->add(new LeafComponent("leaf4"));
composite->add(composite2);
leaf->operation();
composite->operation();
try {
leaf->getChild(0);
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
組合模式形式
透明組合模式
? ? ? ? 抽象構建Component中聲明了所有用于管理成員對象的方法,這樣能確保所有的構建類都有相同的接口。缺點是不夠安全,因為葉子對象和容器對象在本質上是有區(qū)別的。
組合安全模式
????????安全組合模式中,在抽象構件Component中沒有聲明任何用于管理成員對象的方法,而是在Composite類中聲明并實現(xiàn)這些方法。這種做法是安全的,因為根本不向葉子對象提供這些管理成員對象的方法,對于葉子對象,客戶端不可能調用到這些方法。缺點是不夠透明,因為葉子構件和容器構件具有不同的方法,且容器構件中那些用于管理成員對象的方法沒有在抽象構件類中定義,因此客戶端不能完全針對抽象編程,必須有區(qū)別地對待葉子構件和容器構件。
總結
優(yōu)點
? ? ? ? 1.?組合模式可以清楚地定義分層次的復雜對象,表示對象的全部或部分層次。它讓客戶端忽略了層次的差異,方便對整個層次結構進行控制。
? ? ? ? 2.?客戶端可以一致地使用一個組合結構或其中單個對象,不必關心處理的是單個對象還是整個組合結構,簡化了客戶端代碼。
? ? ? ? 3.?在組合模式中增加新的容器構件和葉子構件都很方便,無須對現(xiàn)有類庫進行任何修改,符合開閉原則。
? ? ? ? 4.?組合模式為樹形結構的面向對象實現(xiàn)提供了一種靈活的解決方案。通過葉子對象和容器對象的遞歸組合,可以形成復雜的樹形結構,但對樹形結構的控制卻非常簡單。
缺點
? ? ? ? 1.?在增加新構件時很難對容器中的構件類型進行限制。
適用場景
? ? ? ? 1.?在具有整體和部分的層次結構中,希望通過一種方式忽略整體與部分的差異,客戶端可以一致性地對待它們。
? ? ? ? 2.?在一個使用面向對象語言開發(fā)的系統(tǒng)中需要處理一個樹形結構。
? ? ? ? 3.?在一個系統(tǒng)中能夠分離出葉子對象和容器對象,而且它們的類型不固定,將來需要增加一些新的類型。
練習
myclass.h
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
#include <vector>
class Component {
public:
virtual void display();
virtual void add(Component *component);
virtual void remove(Component *component);
virtual Component *getChild(int i);
protected:
std::string m_name;
};
class Button : public Component {
public:
Button(const std::string &name);
void display() override;
};
class Text : public Component {
public:
Text(const std::string &name);
void display() override;
};
class Window : public Component {
public:
Window(const std::string &name);
void display() override;
void add(Component *component) override;
void remove(Component *component) override;
Component *getChild(int i) override;
private:
std::vector<Component *> m_childs;
};
class Panel : public Component {
public:
Panel(const std::string &name);
void display() override;
void add(Component *component) override;
void remove(Component *component) override;
Component *getChild(int i) override;
private:
std::vector<Component *> m_childs;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp文章來源地址http://www.zghlxwxcb.cn/news/detail-806134.html
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
void Component::display() {
throw std::runtime_error("operation exception");
}
void Component::add(Component *component) {
throw std::runtime_error("add exception");
}
void Component::remove(Component *component) {
throw std::runtime_error("remove exception");
}
Component *Component::getChild(int i) {
throw std::runtime_error("getChild exception");
}
Button::Button(const std::string &name) {
m_name = name;
}
void Button::display() {
std::cout << "Button: " << m_name << std::endl;
}
Text::Text(const std::string &name) {
m_name = name;
}
void Text::display() {
std::cout << "Text: " << m_name << std::endl;
}
Window::Window(const std::string &name) {
m_name = name;
}
void Window::display() {
std::cout << "Window: " << m_name << "包含: " << std::endl;
for (auto it = m_childs.begin(); it != m_childs.end(); ++it) {
(*it)->display();
}
}
void Window::add(Component *component) {
m_childs.push_back(component);
}
void Window::remove(Component *component) {
for (auto it = m_childs.begin(); it != m_childs.end(); ++it) {
if (*it == component) {
m_childs.erase(it);
break;
}
}
}
Component *Window::getChild(int i) {
if (i < m_childs.size()) {
return m_childs[i];
} else {
return nullptr;
}
}
Panel::Panel(const std::string &name) {
m_name = name;
}
void Panel::display() {
std::cout << "Panel: " << m_name << "包含: " << std::endl;
for (auto it = m_childs.begin(); it != m_childs.end(); ++it) {
(*it)->display();
}
}
void Panel::add(Component *component) {
m_childs.push_back(component);
}
void Panel::remove(Component *component) {
for (auto it = m_childs.begin(); it != m_childs.end(); ++it) {
if (*it == component) {
m_childs.erase(it);
break;
}
}
}
Component *Panel::getChild(int i) {
if (i < m_childs.size()) {
return m_childs[i];
} else {
return nullptr;
}
}
到了這里,關于《設計模式的藝術》筆記 - 組合模式的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!