组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。
组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因。
- 组合部件(Component):它是一个抽象角色,为要组合的对象提供统一的接口。
- 叶子(Leaf):在组合中表示子节点对象,叶子节点不能有子节点。
- 合成部件(Composite):定义有枝节点的行为,用来存储部件,实现在Component接口中的有关操作,如增加(Add)和删除(Remove)。
案例:商品关系
源代码:安全模式
package Composite;
import java.util.ArrayList;
import java.util.Collection;
public class Composite {
public static void main(String[] args) {
// TODO Auto-generated method stub
//定义所有的组合对象
Composite1 root=new Composite1("服装");
Composite1 c1=new Composite1("男装");
Composite1 c2=new Composite1("女装");
//定义所有叶子节点
Leaf l1=new Leaf("衬衣");
Leaf l2=new Leaf("夹克");
Leaf l3=new Leaf("裙子");
Leaf l4=new Leaf("套装");
//按照树的结构来组合组合对象和叶子对象
root.addComposite(c1);
root.addComposite(c2);
c1.addLeaf(l1);
c1.addLeaf(l2);
c2.addLeaf(l3);
c2.addLeaf(l4);
root.printStruct(0);
}
}
class Leaf{//叶子节点
private String name="";
public Leaf(String name) {this.name=name;}
public void printStruct(int d) {
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("-"+name);
}
}
class Composite1{//容器节点
private Collection<Composite1> childcomposite =new ArrayList<Composite1>();
private Collection<Leaf>childleaf =new ArrayList<Leaf>();
private String name="";
public Composite1(String name) {
super();
this.name = name;
}
public void addComposite(Composite1 c) {
this.childcomposite.add(c);
}
public void addLeaf(Leaf leaf) {
this.childleaf.add(leaf);
}
public void printStruct(int d) {
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("+"+name);
for(Leaf leaf:childleaf) {
leaf.printStruct(d+2);
}
for(Composite1 c:childcomposite) {
c.printStruct(d+2);
}
}
}
在容器和客户端内区分组合对象和叶子对象并区别对待,程序复杂对功能扩展也带来不便。
改进:抽象出来共同基类继承它产生叶子节点和容器节点。
源代码:透明模式
package Composite;
import java.util.ArrayList;
import java.util.Collection;
public class Composite2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//定义所有的组合对象
Composite1 root=new Composite1("服装");
Composite1 c1=new Composite1("男装");
Composite1 c2=new Composite1("女装");
//定义所有叶子节点
Leaf l1=new Leaf("衬衣");
Leaf l2=new Leaf("夹克");
Leaf l3=new Leaf("裙子");
Leaf l4=new Leaf("套装");
//按照树的结构来组合组合对象和叶子对象
root.Add(c1);
root.Add(c2);
c1.Add(l1);c1.Add(l2);
c2.Add(l3);c2.Add(l4);
root.printStruct(0);
}
}
abstract class Component{
protected String name;
public Component(String name) {
super();
this.name = name;
}
public abstract void Add(Component component);
public abstract void Remove(Component component);
public abstract void printStruct(int component);
}
class Leaf extends Component{//叶子节点
public Leaf(String name) {
super(name);
}
public void printStruct(int d) {
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("-"+name);
}
@Override
public void Add(Component component) {
// TODO Auto-generated method stub
System.out.println("不能添加分支");
}
@Override
public void Remove(Component component) {
// TODO Auto-generated method stub
System.out.println("不能删除分支");
}
}
class Composite1 extends Component{//容器节点
private Collection<Component> components =new ArrayList<Component>();
public Composite1(String name) {
super(name);
}
public void printStruct(int d) {
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("+"+name);
for(Component s:components) {
s.printStruct(d+2);
}
}
@Override
public void Add(Component component) {
// TODO Auto-generated method stub
components.add(component);
}
@Override
public void Remove(Component component) {
// TODO Auto-generated method stub
components.remove(component);
}
}
组合模式框架:
package Composite;
import java.util.ArrayList;
import java.util.Collection;
public class Composite3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//定义所有的组合对象
Composite1 root=new Composite1("root");
//树根,长出两个树叶LeafA和LeafB
root.Add(new Leaf("LeafA"));
root.Add(new Leaf("LeafB"));
//树根长出分支rootx,并有LeafAX和LeafBX
Composite1 rootx=new Composite1("rootx");
rootx.Add(new Leaf("LeafAX"));
rootx.Add(new Leaf("LeafBX"));
root.Add(rootx);
//分支rootx长出分支rootxy,并有LeafAXY和LeafBXY
Composite1 rootxy=new Composite1("rootxy");
rootxy.Add(new Leaf("LeafAXY"));
rootxy.Add(new Leaf("LeafBXY"));
rootx.Add(rootxy);
//树根,长出树叶LeafC
root.Add(new Leaf("LeafC"));
root.printStruct(0);
}
}
abstract class Component{
protected String name;
public Component(String name) {
super();
this.name = name;
}
//增加删除树叶或树枝
public abstract void Add(Component component);
public abstract void Remove(Component component);
public abstract void printStruct(int component);
}
class Leaf extends Component{//叶子节点
public Leaf(String name) {
super(name);
}
public void printStruct(int d) {
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("-"+name);
}
@Override
public void Add(Component component) {
// TODO Auto-generated method stub
System.out.println("不能添加分支");
}
@Override
public void Remove(Component component) {
// TODO Auto-generated method stub
System.out.println("不能删除分支");
}
}
class Composite1 extends Component{//容器节点
private Collection<Component> components =new ArrayList<Component>();
public Composite1(String name) {
super(name);
}
public void printStruct(int d) {//输出格式,缩进
for(int i=0;i<d;i++) {
System.out.print(" ");
}
System.out.println("+"+name);
for(Component s:components) {
s.printStruct(d+2);
}
}
@Override
public void Add(Component component) {
// TODO Auto-generated method stub
components.add(component);
}
@Override
public void Remove(Component component) {
// TODO Auto-generated method stub
components.remove(component);
}
}
1、组合模式的使用场景
当想表达对象的部分-整体的层次结构时。希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。
2、优缺点
- 缺点:客户端需要花更多时间理清类之间的层次关系
- 优点:无需关系处理的单个对象,还是组合的对象容器,实现容器之间的解耦合。当有新部件时容易添加进来。