设计模式之十五:组合模式(Composite)

组合模式:

将对象组合成树形结构来表示部分与整体的关系。组合模式让客户能将单个对象和组合对象统一对待。

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

感觉这是一个很有意思的模式,递归的思路在这里面也得到了体现。如果考虑的业务模型中存在树形结构可以考虑这个模式。

UML图:

主要包括:

  1. Component(DrawingElement):为组合模式中的对象声明了一个接口;实现了一些缺省的行为;声明了一些访问子对象的接口。
  2. Leaf(PrimitiveElement):代表组合模式中的叶节点。叶节点不再包含其它节点。
  3. Composite(CompositeElement):定义有组合对象的行为;包含其它组合对象;实现了对子对象操作的一些接口。

C++代码实现如下:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Component
{
        public:
                Component(string n=string("")):name(n)
                {   

                }
                virtual void add(Component * c)
                {
                }
                virtual void removeComponent(Component * c)
                {

                }
                virtual Component* getChild(int index)
                {

                }
                virtual void display(int depth)=0;

        protected:
                string name;
};

class Leaf:public Component
{
    public:
            Leaf(string str=""):Component(str)
            {

            }
            void display(int depth)
            {
                string str(depth+2,‘-‘);
                std::cout<<str<<name<<std::endl;
            }
};

class Composite:public Component
{
        public:
            Composite(string str=""):Component(str)
            {

            }
            void add(Component* c)
            {
                children.push_back(c);
            }
            void removeComponent(Component *c)
            {
                children.erase( remove(children.begin(),children.end(),c),children.end());
            }
            void display(int depth)
            {
                string str(depth+2,‘-‘);
                std::cout<<str<<name<<std::endl;
                vector<Component*>::iterator iter=children.begin();
                for(;iter!=children.end();iter++)
                        (*iter)->display(depth+1);
            }

            Component* getChild(int index)
            {
                return children[index];
            }

        private:
            vector<Component *> children;

};

int main()
{
    std::cout<<"组合模式例子"<<std::endl;
    Component *root=new Composite("root");
    Component * etc=new Composite("etc");
    Component * mnt=new Composite("mnt");

    root->add(etc);
    root->add(mnt);

    Component * txt1=new Leaf("txt1");
    Component *txt2=new Leaf("txt2");
    etc->add(txt1);
    etc->add(txt2);

    root->display(0);

    std::cout<<std::endl<<std::endl<<"after erase"<<std::endl;
    etc->removeComponent(txt1);
    root->display(0);

    return 0;
}

这里也复习了一下stl容器删除操作。如果提供的是指针,直接进行erase即可,但是如果要删除具有特定值的对象,可以按照下列规则:



对于在内存中连续的顺序容器,如vector,deque,string推荐erase-remove的方法(这种方法对list也可用,但是list有更高效的方法)

vector<int> c;
//注意remove是<algorithm>中的函数
c.erase( remove(c.begin(),c.end(), 25), c.end());


对于list而言,可以使用list的成员函数remove,这样效率会更高一些:

list<int> list_int;
....
list_int.remove(25);  


对于关联容器,可以直接调用erase函数

map<int, int> mapContainer;
...
mapContainer.erase(25); 


执行输出:

下面是一个具体的绘图程序的例子:

  1. Component为DrawingElement,为绘图元素
  2. Leaf为PrimitiveElement,基本的绘图元素,不能再包含其它绘图元素
  3. Composite为CompositeElement

实际上上面的结构是UI中各种元素的简化版,UI中存在各种基本元素,比如按钮,文本框,也包括组合元素,比如各种布局控件,对话框等。它们应该是组合模式一个很好的应用。

UML类图:

C++实现代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class DarawingElement
{
        public:
                DarawingElement(string n=string("")):name(n)
                {   

                }
                virtual void add(DarawingElement * c)
                {
                }
                virtual void removeDarawingElement(DarawingElement * c)
                {

                }
                virtual DarawingElement* getChild(int index)
                {

                }
                virtual void display(int depth)=0;

        protected:
                string name;
};

class PrimitiveElement:public DarawingElement
{
    public:
            PrimitiveElement(string str=""):DarawingElement(str)
            {

            }
            void display(int depth)
            {
                string str(depth+2,‘-‘);
                std::cout<<str<<name<<std::endl;
            }
};

class CompositeElement:public DarawingElement
{
        public:
            CompositeElement(string str=""):DarawingElement(str)
            {

            }
            void add(DarawingElement* c)
            {
                children.push_back(c);
            }
            void removeElement(DarawingElement *c)
            {
                children.erase( remove(children.begin(),children.end(),c),children.end());
            }
            void display(int depth)
            {
                string str(depth+2,‘-‘);
                std::cout<<str<<"+"<<name<<std::endl;
                vector<DarawingElement*>::iterator iter=children.begin();
                for(;iter!=children.end();iter++)
                        (*iter)->display(depth+1);
            }

        private:
            vector<DarawingElement *> children;

};

int main()
{
    std::cout<<"具体的组合模式,画图程序例子"<<std::endl;
    DarawingElement *pic=new CompositeElement("picture");
    DarawingElement * redLine=new PrimitiveElement("red line");
    DarawingElement * blueCircle=new PrimitiveElement("blueCircle");
    DarawingElement * greenBox=new PrimitiveElement("green box");

    pic->add(redLine);
    pic->add(blueCircle);
    pic->add(greenBox);

    DarawingElement * twoCircles=new CompositeElement("two circles");
    DarawingElement * blackCircle=new PrimitiveElement("black circle");
    DarawingElement * whiteCircle=new PrimitiveElement("white Circle");

    twoCircles->add(blackCircle);
    twoCircles->add(whiteCircle);
    pic->add(twoCircles);
    pic->display(1);

    return 0;
}

执行输出:

时间: 2024-10-11 23:49:53

设计模式之十五:组合模式(Composite)的相关文章

设计模式(七)组合模式Composite(结构型)

设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象.客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的.对这些类区别使用,使得程序更加复杂.递归使用的时候跟麻烦,而我们如何

设计模式(二)组合模式Composite(表达式求值)

组合模式目标:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性. 透露一下:这个例子可以说是组合模式的典型应用,据说(作者说)某个编译器开发团队用了两个半月的时间实现了表达式求值,被作者用十几行代码就这样实现了. 需求:表达式求值,是编译器的重要组件,本例你能找到的实际代码应该不多,因为是本人根据<C++沉思录>里面的例子亲自敲出来的(当然都是作者的功劳).目的在于支持各种一元运算,二元运算甚至更多的运算都加入到表达式求值中,程序方便扩展

设计模式(结构型)之组合模式(Composite Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之桥接模式(Bridge Pattern)> http://blog.csdn.net/yanbober/article/details/45366781 概述 组合模式又叫做部分-整体模式,使我们在树型结构的问题中模糊简单元素和复杂元素的概念,客户程序可以像

设计模式(八)组合模式 Composite

组合模式: 允许你将对象组合成树形结构来表现“整体/部分”层次结构.组合能让客户以一致的方式处理个别对象以及对象组合. 组合模式适用于创建复杂的对象,这个对象包含某些个别的对象以及这些对象的组合. 从操作的角度而言,客户端对于 个别对象/组合 的操作是一致的. 模拟场景 如图所示,总公司下属有多个部门,而子公司可以视为多个部门的组合. 整个数据结构呈树状,完美契合组合模式的应用场景. UML: 在这个场景中: 个别对象 -> 人事部(HRDepartment)和财务部(FinanceDepart

Headfirst设计模式的C++实现——组合模式(Composite)

menu_component.h 1 #ifndef _MENU_COMPONENT_H_ 2 #define _MENU_COMPONENT_H_ 3 4 #include <string> 5 6 class MenuComponent { 7 public: 8 class Iterator { 9 public: 10 virtual bool has_next() = 0; 11 12 virtual MenuComponent *next() = 0; 13 }; 14 15 Me

设计模式之组合模式(Composite)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

云计算设计模式(十五)——管道和过滤器模式

云计算设计模式(十五)——管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个应用程序可能需要执行各种关于它处理的信息不同复杂的任务.一个简单,但不灵活的方式来实施这个应用程序可以执行此处理为单一模块.然而,这种方法有可能减少用于重构代码,对其进行优化,或者重新使用它,如果是在应用程序中其他地方所需要的相同的处理的部件的机会. 图1通过使用单片式的方式示出了与处理数据的问题.

设计模式(十五):Iterator迭代器模式 -- 行为型模式

1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用户界面框架中的 Window 对象可以收集任意数量的控制对象 - Menu.Slider 和 Button.并且,集合的实现可以有多种方式:PHP 数字是一个集合,但也是一个散列表,一个链接列表,一个堆栈以及队列. 例子1:电视遥控器的频道遍历 2.问题 如何操纵任意的对象集合? 如一个列表(Lis

设计模式 - 组合模式(composite pattern) 详解

组合模式(composite pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 组合模式: 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方法处理个别对象以及组合对象. 建立组件类(Component), 组合类(composite)和叶子类(leaf)继承组件类, 客户类(client)直接调用最顶层的组合类(composite)即可. 具体方法: 1. 组件类(component), 包含组合

设计模式 - 组合模式(composite pattern) 迭代器(iterator) 详解

组合模式(composite pattern) 迭代器(iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考组合模式(composite pattern): http://blog.csdn.net/caroline_wendy/article/details/36895627 在组合模式(composite pattern)添加迭代器功能, 遍历每一个组合(composite)的项. 具体方法: 1. 抽象组件类(abstract