树形结构在软件中随处可见,比如操作系统中的目录结构,公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题。组合模式通过一种巧妙的设计方案来使得用户可以一致性地处理整个树形结构或者树形结构的一部分,也可以一致地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点).

一 组合模式简介

1.1 模式概述

组合(Composite)模式:组合多个对象形成树形结构以表示具有“整体-部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“部分-整体”(Part-Whole)模式,它是一种对象结构型模式。  

1.2 需求介绍

M公司开发部想要开发一个杀毒软件,该软件既可以针对某个文件夹杀毒,也可以针对某个指定的文件进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现需要提供该杀毒软件的整体框架设计方案。

二 杀毒软件框架设计

  首先在D盘创建如下树结构:

  

2.1 类图

  

2.2 代码实现

2.2.1 抽象文件类

#pragma once

#include <vector>
#include <map> #include <iostream>
using namespace std; // 抽象文件管理类
class CAbsFile
{
public:
CAbsFile(){}
virtual ~CAbsFile(){} virtual void AddFile(CAbsFile *pFile)
{
m_FileVect.push_back(pFile);
} virtual void RemoveFile(string strFileName)
{
vector<CAbsFile*>::iterator iter;
for (iter= m_FileVect.begin(); iter != m_FileVect.end(); iter ++)
{
if ( == strFileName.compare((*iter)->m_strFileName))
{
m_FileVect.erase(iter);
}
}
} virtual CAbsFile* GetChild(string strFileName)
{
vector<CAbsFile*>::iterator iter;
for (iter= m_FileVect.begin(); iter != m_FileVect.end(); iter ++)
{
if ( == strFileName.compare((*iter)->m_strFileName))
{
return *iter;
}
} return NULL;
} virtual void PrintFileStruct()
{
cout << m_strFileName.c_str() <<endl;
vector<CAbsFile*>::iterator iter;
for (iter= m_FileVect.begin(); iter != m_FileVect.end(); iter ++)
{
CAbsFile *pFile = *iter;
pFile->PrintFileStruct();
}
} virtual void DeleteObject()
{
vector<CAbsFile*>::iterator iter;
for (iter= m_FileVect.begin(); iter != m_FileVect.end(); iter ++)
{
CAbsFile *pFile = *iter;
pFile->DeleteObject();
} delete this;
}
virtual void KillVirus() = ; public:
vector<CAbsFile*> m_FileVect;
string m_strFileName;
};

2.2.2 具体text文件类

class CTextFile : public CAbsFile
{
public:
CTextFile(string strFileName)
{
m_strFileName = strFileName;
cout << "CTextFile Construct" << endl;
} ~CTextFile()
{
cout << "CTextFile Deconstruct" << endl;
} void KillVirus()
{
cout << "对文本文件:" << m_strFileName.c_str() << "进行杀毒操作" << endl;
}
};

2.2.3 具体img文件类

class CImgFile : public CAbsFile
{
public:
CImgFile(string strFileName)
{
m_strFileName = strFileName;
cout << "CImgFile Construct" << endl;
} ~CImgFile()
{
cout << "CImgFile Deconstruct" << endl;
} void KillVirus()
{
cout << "对图像文件:" << m_strFileName.c_str() << "进行杀毒操作" << endl;
}
};

2.2.4 具体文件夹类

class CFolder : public CAbsFile
{
public:
CFolder(string strFileName)
{
m_strFileName = strFileName;
cout << "CFolder Construct" << endl;
} ~CFolder()
{
cout << "CFolder Deconstruct" << endl;
} void KillVirus()
{
cout << "对文件夹:" << m_strFileName.c_str() << "进行杀毒操作" << endl;
vector<CAbsFile*>::iterator iter;
for (iter= m_FileVect.begin(); iter != m_FileVect.end(); iter ++)
{
CAbsFile *pFile = *iter;
pFile->KillVirus();
}
}
};

2.3 代码测试

#include "stdio.h"

#include "compose.h"

void main()
{
// 创建文件对象
cout << "创建文件对象" << endl;
CAbsFile *pFolderD = new CFolder("本地磁盘D");
CAbsFile *pFolderComposeTest = new CFolder("ComposeTest");
CAbsFile *pFolderImgFiles = new CFolder("ImgFiles");
CAbsFile *pFolderTextFiles = new CFolder("TextFiles");
CAbsFile *pImgFile = new CImgFile("Image.png");
CAbsFile *pTextFile = new CTextFile("1.txt"); // 构建文件组合
pFolderImgFiles->AddFile(pImgFile);
pFolderTextFiles->AddFile(pTextFile);
pFolderComposeTest->AddFile(pFolderImgFiles);
pFolderComposeTest->AddFile(pFolderTextFiles);
pFolderD->AddFile(pFolderComposeTest);
// 打印文件夹结构
cout << "打印本地磁盘D文件结构" << endl;
pFolderD->PrintFileStruct();
cout <<endl;
// 对composeTest文件夹进程杀毒操作
cout << "对composeTest文件夹进程杀毒操作" << endl;
pFolderComposeTest->KillVirus();
cout << endl; // 对单个img文件进行杀毒操作
cout << "对单个img文件进行杀毒操作" << endl;
pImgFile->KillVirus();
cout <<endl; cout << "释放文件对象" << endl;
pFolderD->DeleteObject();
return;
}

  在具体实现时,可以创建图形界面让用户自己选择所需操作的根节点,无需修改源代码,符合开闭原则,客户端无须关心节点的层次结构,可以对所选节点进行统一处理,提高系统的灵活性。

三 组合模式小结

3.1 主要优点

  (1)可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使客户忽略了层次的差异,方便对整个层次结构进行控制。

  (2)增加新的容器构件和叶子构件都十分方便,无需对现有类库代码进行任何修改,符合开闭原则

  (3)为树形结构的面向对象实现提供了灵活地解决方案,可以形成复杂的树形结构,但对树形结构的控制却很简单

3.2 主要缺点

  增加新构件时很难对容器中的构建类型进行限制。

3.3 适用场景

  (1)在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待他们。

  (2)在一个使用面向对象语言开发的系统中需要处理一个树形结构。

设计模式之组合(compose)模式的更多相关文章

  1. C++设计模式实现--组合(Composite)模式

    一. 举例 这个样例是书上的,如果有一个公司的组结结构例如以下: 它的结构非常像一棵树,当中人力资源部和財务部是没有子结点的,详细公司才有子结点. 并且最关健的是,它的每一层结构非常相似. 代码实现例 ...

  2. Head First 设计模式 —— 11. 组合 (Composite) 模式

    思考题 我们不仅仅要支持多个菜单,升值还要支持菜单中的菜单.你如何处理这个新的设计需求? P355 [提示]在我们的新设计中,真正需要以下三点: P354 我们需要某种属性结构,可以容纳菜单.子菜单和 ...

  3. C#设计模式(10)——组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  4. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  5. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  6. php设计模式七 ---组合模式

    1.介绍 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结 ...

  7. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  8. Java进阶篇设计模式之六 ----- 组合模式和过滤器模式

    前言 在上一篇中我们学习了结构型模式的外观模式和装饰器模式.本篇则来学习下组合模式和过滤器模式. 组合模式 简介 组合模式是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来 ...

  9. 设计模式のCompositePattern(组合模式)----结构模式

    一.产生背景 又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它创建了对象组的树形结构. 这种模 ...

  10. C#设计模式(10)——组合模式(Composite Pattern)(转)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

随机推荐

  1. Set,List,Map的区别

    最近在学习struct2中OGNL表达式的过程中,发现自己对set,list,map存在只是欠缺,在百度的过程中发现了此文觉得讲的不错,放到自己博客以便再次查阅,也希望更多地菜鸟看到. java集合的 ...

  2. E-R图和数据库的设计

    数据库设计: 原则:如果属性有了多个字段,可以当实体.如果只有一个字段,只能当属性(比如实体属性种类) 1.设计E-R图 实体:矩形 关系:菱形 属性:椭圆(可省) 2.关系的类型 一对一 一对多 多 ...

  3. 【笔记】c++文件

    1.文件. #include <iostream> #include <cstdio> #include <string> #include <cstring ...

  4. 20145109 《Java程序设计》第五周学习总结

    20145109 <Java程序设计>第五周学习总结 教材学习内容总结 Chapter 8 Exception Handling try, catch All Exceptions are ...

  5. spark集群安装

    cd到conf中去 修改名字   mv spark-env.sh.template spark-env.sh 并且修改内容 添加: export JAVA_HOME=/root/java/jdk1.8 ...

  6. PAT1054. The Dominant Color (20)

    #include <iostream> #include <map> using namespace std; int n,m; map<int,int> imgM ...

  7. 十二道MR习题 – 1 – 排序

    题目: 一个文件,大小约为100G.文件的每一行都是一个数字,要求对文件中的所有数字进行排序. 对于这个题目,了解过Hadoop的同学可以笑而不语了.即使用spark实现也是非常简单的事情. 先说下如 ...

  8. scala学习手记27 - 下划线与参数

    在Scala里,下划线(_)可以表示函数值的参数.如果某个参数在函数里仅使用一次,就可以用下划线表示.每次在函数里用下划线,都表示随后的参数. val arr = Array(1, 2, 3, 4, ...

  9. ssh登录CentOS服务器(Aliyun)

    ssh登录 (一).在本机使用命令生成ssh密钥:(-C代表注释,如果有多个密钥,加个注释就会很好区分) ssh-keygen -t rsa -C "mingwei" (二).将本 ...

  10. spring3: 表达式5.2 SpEL基础

    5.1  概述 5.1.1  概述 Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行 ...