23种设计模式之(九)组合模式(Composite)
本文主要介绍23种设计模式之组合模式,附详细python/c++示例代码。
- 概念
- 应用场景
- 注意事项
- 代码示例
- 总结
- 代码链接
组合模式(Composite)
概念
组合模式,是构造型的设计模式之一。通过递归手段依据树形结构来组合对象,用来表示部分以及整体层次,并可以通过一个对象来访问整个对象树,把一组相似的对象当作一个单一的对象
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
GoF对组合模式的定义是:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。
应用场景
(1)客户程序需要像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
(2)用户需要忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象(如树形菜单,文件、文件夹的管理)。
代码示例
C++代码示例
/************************************************************************/
/* 设计模式专题
/*
/* 组合模式
/*
/* Author : zzl
/*
/* 编程环境: window10 vs2010
/*
/* Date : 20180916
/************************************************************************/
#include <iostream>
#include "string"
#include "list"
class IFile
{
public:
virtual void display() = 0;
virtual int add(IFile *ifile) = 0;
virtual int remove(IFile *ifile) = 0;
virtual std::list<IFile *>* getChild() = 0;
};
//文件结点
class File : public IFile
{
public:
File(std::string name)
{
m_name = name;
}
virtual void display()
{
printf("%s\n",m_name.c_str());
}
virtual int add(IFile *ifile)
{
return -1;
}
virtual int remove(IFile *ifile)
{
return -1;
}
virtual std::list<IFile *>* getChild()
{
return NULL;
}
private:
std::string m_name;
};
//目录 结点
class Dir : public IFile
{
public:
Dir(std::string name)
{
m_name = name;
m_list = new std::list<IFile *>;
m_list->clear();
}
virtual void display()
{
printf("%s\n",m_name.c_str());
}
virtual int add(IFile *ifile)
{
m_list->push_back(ifile);
return 0;
}
virtual int remove(IFile *ifile)
{
m_list->remove(ifile);
return 0;
}
virtual std::list<IFile *>* getChild()
{
return m_list;
}
private:
std::string m_name;
std::list<IFile *> *m_list;
};
// 递归的显示树
void showTree(IFile *root, int level)
{
int i = 0;
if (root == NULL)
{
return ;
}
for (i=0; i<level; i++)
{
printf("\t");
}
//1 显示根 结点
root->display();
//2 若根结点 有孩子
//判读孩子是文件,显示名字 )
//判断孩子是目录,showTree(子目录)
std::list<IFile *> *mylist = root->getChild();
if (mylist != NULL) //说明是一个目录
{
for (std::list<IFile *>::iterator it=mylist->begin(); it!=mylist->end(); it++)
{
if ( (*it)->getChild() == NULL )
{
for (i=0; i<=level; i++) //注意 <=
{
printf("\t");
}
(*it)->display();
}
else
{
showTree(*it, level+1);
}
}
}
}
void main()
{
Dir *root = new Dir("C");
//root->display();
Dir *dir1 = new Dir("111dir");
File *aaafile = new File("aaa.txt");
//获取root结点下的 孩子集合
std::list<IFile *> *mylist = root->getChild();
root->add(dir1);
root->add(aaafile);
for ( std::list<IFile *>::iterator it=mylist->begin(); it!=mylist->end(); it++ )
{
(*it)->display();
}
Dir *dir222 = new Dir("222dir");
File *bbbfile = new File("bbb.txt");
dir1->add(dir222);
dir1->add(bbbfile);
printf("--------showTree---------\n");
showTree(root, 0);
}
python代码示例
# -*- coding: utf-8 -*-
###################################################################
# 设计模式专题
#
# 组合模式
#
# Author : zzl
#
# 编程环境: window10 python2.7
#
# Date : 20180916
##################################################################
class IFile(object):
def display(self):
pass
def add(self, ifile):
pass
def remove(self, ifile):
pass
def get_child(self):
pass
# 文件结点
class File(IFile):
def __init__(self, name):
self.m_name = name
def display(self):
print(self.m_name)
def add(self, ifile):
return -1
def remove(self, ifile):
return -1
def get_child(self):
return None
# 目录结点
class Dir(IFile):
def __init__(self, name):
self.m_name = name
self.m_list = []
m_name = name
def display(self):
print(self.m_name)
def add(self, ifile):
self.m_list.append(ifile)
def remove(self, ifile):
self.m_list.remove(ifile)
def get_child(self):
return self.m_list
def show_tree(root, level):
if not root:
return
for i in range(level):
print "\t",#python2.7 打印不换行
# 1、显示根结点
root.display()
# 2、若根结点有孩子
# 判读孩子是文件, 显示名字
# 判断孩子是目录, showTree(子目录)
mylist = root.get_child()
if mylist: # 说明是一个目录
for child in mylist:
if not child.get_child():
for i in range(level + 1):
print "\t", #python2.7 打印不换行
child.display()
else:
show_tree(child, level + 1)
if __name__ == "__main__":
root = Dir("C")
dir1 = Dir("111dir")
aaafile = File("aaa.txt")
# 获取root结点下的孩子集合
mylist = root.get_child()
root.add(dir1)
root.add(aaafile)
for child in mylist:
child.display()
dir222 = Dir("222dir")
bbbfile = File("bbb.txt")
dir1.add(dir222)
dir1.add(bbbfile)
print("--------showTree---------")
show_tree(root, 0)