C++设计模式之组合模式

C++设计模式之组合模式攻略

简介

组合模式(Composite Pattern)是一种结构型设计模式。组合模式可以将对象组合成树形结构,表示“部分-整体”的结构层次关系,让客户端统一对待单个对象和组合对象。

结构

组合模式将对象组织成树形结构,有以下三个角色:

Component(抽象构件)

抽象构件定义了叶子和容器构件的公共接口,并可以提供一些默认的行为或属性。

class Component {
public:
    virtual ~Component() {}
    virtual void operation() = 0;
};

Leaf(叶子构件)

叶子构件是组成对象的最基本单元,其没有子节点,实现了抽象构件中的操作。

class Leaf : public Component {
public:
    virtual void operation() {
        // 叶子构件的操作
    }
};

Composite(容器构件)

容器构件包含一组子节点,其中部分或所有子节点是另一个容器构件,其实现了抽象构件中的操作,并且可以在内部管理子节点。

class Composite : public Component {
private:
    vector<Component*> components;
public:
    virtual void operation() {
        for (auto c : components) {
            c->operation();
        }
    }
    void addComponent(Component* c) {
        components.push_back(c);
    }
    void removeComponent(Component* c) {
        // 移除指定子节点
    }
};

示例1:菜单栏

假设我们正在开发一个图形界面程序,需要实现一个具备子菜单的菜单栏。用组合模式可以轻松实现该功能。

int main() {
    Composite* menuBar = new Composite;  // 菜单栏
    Composite* fileMenu = new Composite;  // 文件菜单
    Composite* editMenu = new Composite;  // 编辑菜单
    Leaf* openItem = new Leaf;  // 打开文件项
    Leaf* saveItem = new Leaf;  // 存储文件项
    Leaf* copyItem = new Leaf;  // 复制项
    Leaf* pasteItem = new Leaf;  // 粘贴项
    fileMenu->addComponent(openItem);
    fileMenu->addComponent(saveItem);
    editMenu->addComponent(copyItem);
    editMenu->addComponent(pasteItem);
    menuBar->addComponent(fileMenu);
    menuBar->addComponent(editMenu);
    menuBar->operation(); // 显示菜单栏及其子菜单
    return 0;
}

示例2:文件系统

下面是一个文件系统的例子。文件系统由一个根目录和多个文件和子目录组成。

class FileSystemNode {
public:
    virtual ~FileSystemNode() {}
    virtual int getNumOfFiles() = 0;
    virtual int getSize() = 0;
    virtual string getName() = 0;
    virtual void addNode(FileSystemNode* node) = 0;
    virtual void removeNode(FileSystemNode* node) = 0;
};

class File : public FileSystemNode {
public:
    File(const string& name, int size) : name_(name), size_(size) {}
    virtual int getNumOfFiles() { return 1; }
    virtual int getSize() { return size_; }
    virtual string getName() { return name_; }
    virtual void addNode(FileSystemNode* node) {}
    virtual void removeNode(FileSystemNode* node) {}
private:
    string name_;
    int size_;
};

class Directory : public FileSystemNode {
public:
    Directory(const string& name) : name_(name), size_(0) {}
    virtual ~Directory() {
        for (auto n : nodes_) {
            delete n;
        }
    }
    virtual int getNumOfFiles() {
        int count = 0;
        for (auto n : nodes_) {
            count += n->getNumOfFiles();
        }
        return count;
    }
    virtual int getSize() { return size_; }
    virtual string getName() { return name_; }
    virtual void addNode(FileSystemNode* node) {
        nodes_.push_back(node);
        size_ += node->getSize();
    }
    virtual void removeNode(FileSystemNode* node) {
        auto it = find(nodes_.begin(), nodes_.end(), node);
        if (it != nodes_.end()) {
            nodes_.erase(it);
            size_ -= node->getSize();
        }
    }
private:
    string name_;
    int size_;
    vector<FileSystemNode*> nodes_;
};

int main() {
    Directory* root = new Directory("R:");
    Directory* cDrive = new Directory("C:");
    Directory* dDrive = new Directory("D:");
    File* msPaint = new File("mspaint.exe", 112);
    File* myFile = new File("myFile.txt", 10);
    Directory* music = new Directory("Music");
    root->addNode(cDrive);
    root->addNode(dDrive);
    cDrive->addNode(msPaint);
    cDrive->addNode(myFile);
    dDrive->addNode(music);
    music->addNode(new File("song1.mp3", 8));
    music->addNode(new File("song2.mp3", 9));
    music->addNode(new Directory("Pop"));
    music->addNode(new Directory("Rock"));
    cout << "Num of files: " << root->getNumOfFiles() << endl;
    cout << "Total size: " << root->getSize() << endl;
    return 0;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++设计模式之组合模式 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 浅析C/C++ 中return *this和return this的区别

    浅析C/C++ 中 return *this 和 return this 的区别 在 C/C++ 中,this 指针指向当前对象,*this 则代表对象本身。在函数中,return *this 和 return this 实现的功能大致相同,但是两者仍有一定的区别。 return *this return *this 关键字语句出现时,函数返回的是对象本身,…

    C 2023年5月23日
    00
  • 汇编基础程序编写教程示例

    下面是关于“汇编基础程序编写教程示例”的完整攻略。 汇编基础程序编写教程示例 什么是汇编语言? 汇编语言是一种计算机语言,其提供给程序员一种直接在机器上运行程序的方法。通过使用纯文本方式编写的汇编程序,程序员可以方便地对程序进行调试、优化和理解。 汇编语言的基本语法和应用 汇编语言是由一种或多种机器指令组成的程序语言,具有紧凑、高效和占用计算机资源少的优点。…

    C 2023年5月30日
    00
  • 浅谈go中cgo的几种使用方式

    浅谈 Go 中 Cgo 的几种使用方式 Cgo 是 Go 语言中的一个重要特性,它可以被用来在 Go 代码中调用 C 语言函数。Cgo 是 Go 语言最独特的特性之一,它可以让开发者直接使用 C 代码功能,也可以将 Go 代码转为 C 代码,这样就可以在 Go 中直接使用 C 库,同时也能够保证 Go 语言的安全性。 Cgo 中的基本使用 使用 Cgo 调用…

    C 2023年5月23日
    00
  • 浅析Java异常处理中断言的使用

    浅析Java异常处理中断言的使用 Java异常处理机制允许程序在出现错误和异常时进行优雅的处理,从而保证程序的安全性和稳定性。而其中断言(assertion)机制则是一种非常强大的调试工具,可以在程序出现错误时,中断程序并给出特定的提示,帮助程序员更快地定位和修复问题。 在本篇攻略中,我们将分为以下几个部分,详细讲解Java异常处理中断言的原理、用法及注意事…

    C 2023年5月23日
    00
  • C语言简明讲解预编译的使用

    首先我们需要了解预编译器是什么,预处理指令的作用是什么,在C语言中如何使用预编译器。 什么是预编译器? 预编译器是C语言编译器的一部分,它是在编译正式开始之前处理源代码的一段程序。预编译器处理的代码包括头文件和宏定义等,在编译正式开始之前,预编译器将对这些代码进行处理并将处理后的代码输出,交给编译器进行编译。预编译器的处理结果就是一个纯C语言代码的文件。 预…

    C 2023年5月23日
    00
  • C语言通讯录管理系统完整代码

    C语言通讯录管理系统完整代码攻略 概述 本文将介绍C语言实现的通讯录管理系统的完整代码,并且对代码进行详细讲解说明。该代码实现的功能包括通讯录的增加、删除、修改、查询和展示等。 代码说明 代码结构 该代码主要分为两个文件,一个是 main.c,另一个是 contacts.h。其中 main.c 中包含了程序的入口 main 函数以及 contacts.h 的…

    C 2023年5月23日
    00
  • 利用C语言实现“百马百担”问题方法示例

    利用C语言实现“百马百担”问题方法示例 什么是“百马百担”问题? “百马百担”问题是一个著名的有趣问题。大致内容如下:有一百匹马、一百个马夫,他们需要将一百担货物运送到目的地。每匹马可以携带一担货物,每个马夫可以驾驭一匹或多匹马。假设每匹马的运载能力相同,每个马夫的驾驶能力也相同,同时任何马夫都可以搭乘一匹或多匹马。请问至少需要多少个马夫才能全部将货物运送到…

    C 2023年5月23日
    00
  • thinkphp下MySQL数据库读写分离代码剖析

    下面是“thinkphp下MySQL数据库读写分离代码剖析”的完整攻略,包含了步骤、示例代码和注意点。 步骤 1. 安装MySQL主从复制 首先,需要安装MySQL主从复制功能,将主服务器的数据同步到从服务器,实现读写分离。 2. 配置主从服务器 在主服务器和从服务器中,分别配置MySQL的主从关系和各自的配置文件。在配置文件中,需要设置数据库的用户名、密码…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部