设计模式学习-组合模式

设计模式学习-组合模式

文章理论部分感谢以下链接

http://www.runoob.com/design-pattern/composite-pattern.html

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示“部分-整体”的层次结构。这种类型的设计模式属于结构型模式,它创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

组合模式介绍

意图:将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作树、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项:定义时为具体类。

UML结构图

抽象基类:
1、Component:为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数),声明一个接口函数可以访问Component的子组件。
接口函数:
1、Component::Operatation:定义了各个组件共有的行为接口,由各个组件具体实现.
2、Component::Add添加一个子组件
3、Component::Remove::删除一个子组件.
4、Component::GetChild:获得子组件的指针
解析:
Component模式是为解决组件之间的递归组合提供了解决的办法,它主要分为两个派生类,其中的Leaf是叶子结点,也就是不含有子组件的结点,而Composite是含有子组件的类。举一个例子来说明这个模式,在UI的设计中,最基本的控件是诸如Button, Edit这样的控件,相当于是这里的Leaf组件,而比较复杂的控件比如List则可也看做是由这些基本的组件组合起来的控件,相当于这里的Composite,它们之间有一些行为含义是相同的,比如在控件上作一个点击,移动操作等等的,这些都可以定义为抽象基类中的接口虚函数,由各个派生类去实现之,这些都会有的行为就是这里的Operation函数,而添加,删除等进行组件组合的操作只有非叶子结点才可能有,所以虚拟基类中只是提供接口而且默认的实现是什么都不做。

实现演练

1、对应着UML结构图的实现代码

#include<iostream>
#include<list>
using namespace std;
//组合中的抽象基类
class Component
{
public:
    Component(){}
    virtual ~Component(){}
    //纯虚函数,只提供接口,没有默认的实现

    virtual void Operation()=0;
    //虚函数,提供接口,有默认的实现就是什么都不做
    virtual void Add(Component* pChild){}
    virtual void Remove(Component* pChild){}
    virtual Component* GetChild(int nIndex)
    { 
        return NULL; 
    }
};
//派生自Component,是其中的叶子组件的基类
class Leaf:public Component
{
public:
    Leaf(){}
    virtual ~Leaf(){}
    virtual void Operation()
    { 
        cout<<"Operation by Leaf"<<endl; 
    }
};
//派生自Component,是其中含有子间的组件的基类
class Composite:public Component
{
public:
    Composite(){}
    virtual ~Composite()
    {
        list<Component*>::iterator iter1,iter2,temp;
        for(iter1=m_ListOfComponent.begin(),iter2= m_ListOfComponent.end(); iter1!=iter2;)
        {
            temp = iter1;
            ++iter1;
            delete(*temp);
        }
    }
    virtual void Operation()
    {
        cout<<"Operation by Conposite"<<endl;
        list<Component*>::iterator iter1,iter2;
        for(iter1=m_ListOfComponent.begin(),iter2= m_ListOfComponent.end();  iter1!=iter2;++iter1)
            (*iter1)->Operation();
    }
    virtual void Add(Component* pChild)
    { 
        m_ListOfComponent.push_back(pChild); 
    }
    virtual void Remove(Component* pChild)
    {
        list<Component*>::iterator iter;
        iter = find(m_ListOfComponent.begin(), m_ListOfComponent.end(), pChild);
        if(m_ListOfComponent.end()!=iter)
        { 
            m_ListOfComponent.erase(iter); 
        }
    }
    virtual Component* GetChild(int nIndex)
    {
        if(nIndex<=0||nIndex>m_ListOfComponent.size())
            return NULL;
        list<Component*>::iterator iter1,iter2;
        int i;
        for(i=1,iter1=m_ListOfComponent.begin(), iter2= m_ListOfComponent.end();iter1!=iter2;++iter1,++i)
        {
            if(i==nIndex)
                break;
        }
        return *iter1;
    }
private:
    //采用list容器去保存子组件
    list<Component*> m_ListOfComponent;
};
int main()
{
    Leaf* pLeaf1 = new Leaf();
    Leaf* pLeaf2 = new Leaf();
    Composite* pComposite = new Composite;
    pComposite->Add(pLeaf1);
    pComposite->Add(pLeaf2);
    pComposite->Operation();
    pComposite->GetChild(2)->Operation();
    delete pComposite;
    return 0;
}

2、修改网上的演练代码,展示了一个组织中员工的层次结构。
(1)首先创建一个员工的基类

class Employee 
{
   //构造函数
public:
    Employee(){}
    virtual ~Employee(){}
    Employee(string name,string dept) 
    {
      m_Name = name;
      m_Dept = dept;
    }
    //纯虚函数,只提供接口,没有默认的实现
    virtual void Operation()=0;
    //虚函数,提供接口,有默认的实现就是什么都不做
    virtual void Add(Employee* pChild){}
    virtual void Remove(Employee* pChild){}
    virtual Employee* GetChild(int nIndex)
    { 
       return   NULL; 
    }

protected:
   string m_Name;
   string m_Dept;
};

(2)继承自员基类的普通职工,它没有下属,所以相当于叶子组件

//派生自Employee,是其中的叶子组件的基类
class clerk:public Employee
{
public:
    clerk(){}
    clerk(string name,string dept) 
    {
      m_Name = name;
      m_Dept = dept;
    }
    virtual ~clerk(){}
    virtual void Operation()
    { 
        cout<<"Operation by clerk"<<endl; 
        cout<<" Name : "<<m_Name+", dept : "<<m_Dept<<endl;
    }   
};

(3)继承自员基类的经理类,它拥有下属

//派生自Component,是其中含有子间的组件的基类
class Manager:public Employee
{
public:
    Manager(){}
    Manager(string name,string dept) 
    {
      m_Name = name;
      m_Dept = dept;
    }
    virtual ~Manager()
    {
        list<Employee*>::iterator iter1,iter2,temp;
        for(iter1=m_ListOfComp.begin(),iter2= m_ListOfComp.end(); iter1!=iter2;)
        {
            temp = iter1;
            ++iter1;
            delete(*temp);
        }
    }
    virtual void Operation()
    {
        cout<<"Operation by Manager"<<endl;
        cout<<" Name : "<<m_Name+", dept : "<<m_Dept<<endl;
        list<Employee*>::iterator iter1,iter2;
        for(iter1=m_ListOfComp.begin(),iter2= m_ListOfComp.end();  iter1!=iter2;++iter1)
            (*iter1)->Operation();
    }
    virtual void Add(Employee* pChild)
    { 
        m_ListOfComp.push_back(pChild); 
    }
    virtual void Remove(Employee* pChild)
    {
        list<Employee*>::iterator iter;
        iter = find(m_ListOfComp.begin(), m_ListOfComp.end(), pChild);
        if(m_ListOfComp.end()!=iter)
        { 
            m_ListOfComp.erase(iter); 
        }
    }
    virtual Employee* GetSubordinates(int nIndex)
    {
        if(nIndex<=0||nIndex>m_ListOfComp.size())
            return NULL;
        list<Employee*>::iterator iter1,iter2;
        int i;
        for(i=1,iter1=m_ListOfComp.begin(), iter2= m_ListOfComp.end();iter1!=iter2;++iter1,++i)
        {
            if(i==nIndex)
                break;
        }
        return *iter1;
    }
private:
    //采用list容器去保存子组件
    list<Employee*> m_ListOfComp;
};

(4)测试的主函数

int main()
{

    //Test2();
    Employee *pM = new Manager("Zhao","1");
    Employee *c1 = new clerk("Zhang","1");
    Employee *c2 = new clerk("Zhang","1");
    pM->Add(c1);
    pM->Add(c2);
    pM->Operation();

    delete pM;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值