组合模式
定义:
将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
也称为 整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性。
结构图:
组合模式分为透明方式和安全方式,区别就是在Component基类中是否声明所有接口:
透明方式:在Component中声明所有用来管理子类的方法;坏处是对于叶子对象来说有些接口是没有意义的。好处是客户端不需要做相应的判断;
安全模式;在Component只声明系统各个层次的最基础的一致行为,而把有用来管理子类的方法放到Composite当中;坏处是由于树枝和叶子类不具有相同的接口,客户端调用时需要做相应的判断。好处是叶子对象不需要实现多余的方法。
代码(创建文件夹目录系统,包含组合对象:文件夹和单个对象:文件):(安全模式)
//抽象根类:Component,只定义最基础行为:
Display
class Directory
{
protected:
String name;
public:
Directory
(String name)
{
this.name = name;
}
void Display
() = 0;
}
//树枝节点:Composite
class Folder : Directory
{
private:
List<Directory> mDirs;
public:
Folder(String name)
{ this.name = name;
this.mDirs = new ArrayList<>();
}
void Display
()
{
System.out.println(this.name + “: Folder”);
foreach ( Directory in mDirs)
{
Directory.Display
();
}
}
//树枝节点中新增自己的管理方法
void addDir(Directory dir)
{
return this.mDirs.add(dir);
}
void removeDir(Directory dir)
{
return this.mDirs.remove(dir);
}
}
//叶子节点:Leaf
class File : Directory
{
public:
File(String name)
{
this.name = name;
}
void Display
()
{
System.out.println(this.name + “: file”);
}
}
//客户端 (对于客户端来说文件和文件夹的display没有区别,文件夹和文件的区别只是否有增删接口而已,在透明模式中,甚至不需要客户端知道区别)
Folder A = new Folder(“A”);//创建文件夹A
File Ax = new File(“Ax”);//创建文件Ax
File Ay = new File(“Ay”);//创建文件Ay
A.addDir(Ax);//添加文件Ax
A.addDir(Ax);//添加文件Ay
A.Display();
使用时机:
系统对象层次具备整体和部分,呈树形结构,且要求具备统一行为,以及希望客户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时(如树形菜单,操作系统目录结构,公司组织架构等);
优点:
1、组合模式可以让用户一致的使用组合结构(树枝)和单个对象(树叶)。
2、可以很方便地增加 树枝节点 和 叶子节点 对象,并对现有类库无侵入,符合 开闭原则;
缺点:如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系;