介绍
也称为整体部分模式,结构型设计模式之一,组合模式比较简单,他将一组相似的对象看作一个对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问响应的对象,以此忽略掉对象跟对象集合之间的差别。生活中比较典型的例子就是组织结构的树状图。
一个公司有行政部,研发部,同时还有子公司,子公司里也有行政部跟研发部。
在这里虽然总公司跟子公司其本质不一样,但是他们的组织结构是一样的,我们可以把他们看作是一个抽象的公司,在组合模式中我们将这样一个拥有分支的节点称之为枝干构件,位于树状结构顶部的枝干结构比较特殊,我们称之为根结构件,因为其为整个树状结构的始端,同样对于像行政部和研发部这样的没有分支的结构,我们则称之为叶子构件,这样的一个结构就是组合模式的雏形。
标准定义:将对象组合成树形结构以表示”整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
使用场景
- 表示对象的部分-整体层次结构的时候
- 从一个整体中能够独立出部分模块或功能的场景
角色介绍
- Component
- Composite
- Leaf
- Client
Component :抽象根节点,为组合中的对象声明接口。在适当情况下,实现所有类共有接口的缺省的行为。声明一个结构用于访问跟管理Component的子节点。可在递归结构中定一个接口,用于访问一个父节点,并在合适的时候,实现它。
Composite:定义有子节点的那些枝干节点的行为,存储子节点,在Component接口中实现与子节点有关的操作。
Leaf:在组合中表示叶子节点对象,叶子节点没有子节点,在组合中定义节点对象的行为。
Client:通过Component接口操纵组合节点的对象。
组合模式的模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public abstract class Component {
protected String name;
public Component(String name){ this.name=name; }
public abstract void doSomething();
public abstract void addChild(Component child);
public abstract void rmvChild(Component child);
public abstract Component getChildren(int index);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class Composite extends Component {
private List<Component> components = new ArrayList<>();
public Composite(String name) { super(name); }
@Override public void doSomething() { System.out.println(name); if(null!=components){ for(Component c:components){ c.doSomething(); } } }
@Override public void addChild(Component child) { components.add(child); }
@Override public void rmvChild(Component child) { components.remove(child); }
@Override public Component getChildren(int index) { return components.get(index); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class Leaf extends Component {
public Leaf(String name) { super(name); }
@Override public void doSomething() { System.out.println(name); }
@Override public void addChild(Component child) { throw new UnsupportedOperationException("子类型不支持该操作"); }
@Override public void rmvChild(Component child) { throw new UnsupportedOperationException("子类型不支持该操作"); }
@Override public Component getChildren(int index) { throw new UnsupportedOperationException("子类型不支持该操作"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Client {
public static void main(String[] args){
Component root = new Composite("Root");
Component branch1 = new Composite("Branch1"); Component branch2 = new Composite("Branch2");
Component leaf1 = new Leaf("Leaf1"); Component leaf2 = new Leaf("Leaf2");
branch1.addChild(leaf1); branch2.addChild(leaf2);
root.addChild(branch1); root.addChild(branch2);
root.doSomething();
}
}
|
简单实现
操作系统的文件系统
表示文件或者文件夹的抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public abstract class Dir {
//存储文件夹下的所有的元素 protected List<Dir> dirs = new ArrayList<>();
//文件或者文件夹的名字 private String name;
public Dir(String name){ this.name=name; }
//添加一个文件或者文件夹 public abstract void addDir(Dir dir);
//移除一个文件或者文件夹 public abstract void rmDir(Dir dir);
//清空 public abstract void clear();
//输出文件目录结构 public abstract void print();
//获取文件夹下的所有文件或者文件夹 public abstract List<Dir> getFiles();
//获取文件或者文件夹的名字 public String getName(){ return name; }
}
|
文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class Folder extends Dir {
public Folder(String name) { super(name); }
@Override public void addDir(Dir dir) { dirs.add(dir); }
@Override public void rmDir(Dir dir) { dirs.remove(dir); }
@Override public void clear() { dirs.clear(); }
//首先输出自己的名字,然后迭代遍历子元素,调用子元素的print方法输出其目录结构, // 如果遇到子元素还是个文件夹,那么递归遍历直至所有的输出元素均为文件为止。 @Override public void print() {
System.out.print(getName()+"("); Iterator<Dir> iterator = dirs.iterator(); while(iterator.hasNext()){
Dir dir = iterator.next(); dir.print(); if(iterator.hasNext()){ System.out.print(","); } } System.out.print(")");
}
@Override public List<Dir> getFiles() { return dirs; } }
|
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class File extends Dir {
public File(String name) { super(name); }
@Override public void addDir(Dir dir) { throw new UnsupportedOperationException("文件对象不支持该操作"); }
@Override public void rmDir(Dir dir) { throw new UnsupportedOperationException("文件对象不支持该操作"); }
@Override public void clear() { throw new UnsupportedOperationException("文件对象不支持该操作"); }
@Override public void print() { System.out.print(getName()); }
@Override public List<Dir> getFiles() { throw new UnsupportedOperationException("文件对象不支持该操作"); } }
|
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class client {
public static void main(String[] args){
Dir diskC = new Folder("C");
diskC.addDir(new File("first.text"));
Dir dirWin = new Folder("windows"); dirWin.addDir(new File("explorer.exe"));
diskC.addDir(dirWin);
Dir dirPer = new Folder("PerfLogs"); dirPer.addDir(new File("null.txt"));
diskC.addDir(dirPer);
Dir dirPro = new Folder("Program File"); dirPro.addDir(new File("ftp.txt"));
diskC.addDir(dirPro);
diskC.print();
} }
|
上一篇:命令模式
下一篇:原型模式