设计模式学习(十四) 组合模式


这是个人学习编程模式的系列学习笔记第十四篇。
采用Qt Creator进行编写,但尽量采用C++基础语法。
组合模式(Composite Pattern):将对象组合成树形结构以表示“部分 -整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式可以方便构建树型结构组织,比如总公司、分公司、办事处,每一级有可以有自己的具体部门,比如财务,人事。可以将各级公司作为树干或树枝,在树干或树枝上可以生长树叶(具体的部门,比如财务部,人事部,这些树叶不具备下一级),也可以生长下一级树枝(分公司、办事处)。
可以将全部部门按统一的抽象接口来实现。比如人事部没有下一级部门,依然提供新增下一级部门的接口,但不实现具体的功能。这种方式称为透明方式。这样的方式不需要调用者判断对象是否有对应的方法。
另外一种方式是安全方式。统一接口只定义大家都必须有的接口,这样的方式,调用者需要判断调用的对象是否具备这个功能。

场景描述

文件管理系统就是这样的树形结构,目录就是树枝,文件是树叶。目录下面可以有子目录,也可以有文件。
创建一个简单的文件管理系统,模拟对目录和文件的管理。

设计思路

将目录或文件抽象为一个统一的通用文件对象,可以有add、delete、show。add可以在下级增加一个目录或文件,delete可以删除下级的一个空目录或文件,show显示当前节点的全部下级内容。

UML

在这里插入图片描述

代码

#include <iostream>
#include <list>
using namespace std;

class Component
{
public:
    Component(string name) : m_name(name) {}
    virtual void add(Component *c) = 0;
    virtual void del(Component *c) = 0;
    virtual void show(int depth) = 0;
    virtual string whoami() {return "Component";}

public:
    string m_name;
};

class File : public Component
{
public:
    File(string name) : Component(name) {}
    void add(Component *c) {}
    void del(Component *c) {}
    void show(int depth)
    {
        for(int i = 0; i <= depth; i++) cout<<"--";
        cout<<"file: "<<m_name<<"\n";
    }
    virtual string whoami() {return "File";}
};

class Directory : public Component
{
public:
    Directory(string name) : Component(name) {}
    void add(Component *c) { m_children.push_back(c);}
    void del(Component *c)
    {
        string str = c->whoami();
        if(str == "File")
        {
            m_children.remove(c);
            cout<<"Del a file success!\n";
        }
        else if(str == "Directory")
        {
            if(static_cast<Directory *> (c)->m_children.empty()) m_children.remove(c);
            else cout<<"Cann\'t del nonempty directory!\n";
        }
    }
    void show(int depth)
    {
         for(int i = 0; i <= depth; i++) cout<<"--";
        cout<<"directory: "<<m_name<<"\n";
        list<Component *>::iterator iter;
        for(iter = m_children.begin(); iter != m_children.end() ; iter++)
        {
            (*iter)->show(depth + 1);
        }
    }
    virtual string whoami() {return "Directory";}
public:
    list<Component *> m_children;
};

int main()
{
    Directory dir("firstDIR");
    Directory dir1("secondDIR");
    Directory dir2("thirdDIR");
    File file("file");
    dir.add(&dir1);
    dir1.add(&file);
    dir1.add(&dir2);
    dir.show(0);
    dir.del(&dir1);
    dir1.del(&file);
    dir.show(0);
    return 0;
}

运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值