今天学习了组合模式,刚开始在网上看例子的时候,感觉很乱,而且没有一个比较具体的例子,所以特意想了一个例子,并且用组合模式实现,最后我给出了结构图,有助于各位的理解。
组合模式的适用范围是用户需要忽略组合对象与单个对象的差异。这句话反正我是看不懂,举个例子来讲,我们买了一台笔记本电脑,但是用了一段时间之后坏了,我们就需要去维修部修理,维修部门有两种,一种是电脑官方的维修部门,还有一种是个人代理,官方授权的维修部门,这两个部门虽然性质不一样,但是对于我们用户来说,他们是一样的,都是在修电脑,我们不必关心在哪里修的,只要最后能用,就是我们想要的结果。
那我们就拿这个作为例子,敲一遍代码,理解的会更深刻
先看包结构
好,我们先来建立一个抽象类,这个抽象类是我们每个维修部门都要履行的职责
package com.component.abs;
/**
* 电脑维修的抽象类,每个维修部都要继承
* @author ZHENGWEI
* @date Aug 4, 2015
*/
public abstract class AcerComponent {
//维修部门的名称,比如北京朝阳区维修部,XXXX个人代理维修部等。
protected String mantainName;
public AcerComponent(String mantainName) {
super();
this.mantainName = mantainName;
}
/**
* 增加维修部门的方法,形成树形关系
* @param ac
*/
public abstract void addMaintainDepartment(AcerComponent ac);
/**
* 去掉维修部门的方法
* @param ac
*/
public abstract void removeMaintainDepartment(AcerComponent ac);
/**
* 具体操作的方法
*/
public abstract void display();
}
之后就是那两种不同的维修部
package com.component.leaf;
import com.component.abs.AcerComponent;
/**
* 叶子节点,这里代表个人代理部,没有下属的分公司
* @author ZHENGWEI
* @date Aug 4, 2015
*/
public class AcerMantainLeaf extends AcerComponent{
public AcerMantainLeaf(String mantainName) {
super(mantainName);
}
@Override
public void addMaintainDepartment(AcerComponent ac) {
System.out.println("个人代理,无法增加");
}
@Override
public void removeMaintainDepartment(AcerComponent ac) {
System.out.println("个人代理,无法删除");
}
/**
* 由于是个人代理,所以只显示自己的名字就OK了
*/
@Override
public void display() {
System.out.println(this.mantainName);
}
}
package com.component.composite;
import java.util.ArrayList;
import java.util.List;
import com.component.abs.AcerComponent;
/**
* 官方下属的分公司
* @author ZHENGWEI
* @date Aug 4, 2015
*/
public class AcerMantainComposite extends AcerComponent{
List<AcerComponent> mantainList = new ArrayList<AcerComponent>();
public AcerMantainComposite(String mantainName) {
super(mantainName);
}
@Override
public void addMaintainDepartment(AcerComponent ac) {
this.mantainList.add(ac);
}
@Override
public void removeMaintainDepartment(AcerComponent ac) {
this.mantainList.remove(ac);
}
@Override
public void display() {
System.out.println(this.mantainName);
for(AcerComponent ac : mantainList){
ac.display();
}
}
}
最后是测试类,这个类写的不太好,有些乱,不过我在最后给大家放一张图,有助于大家理解
package com.component.main;
import com.component.abs.AcerComponent;
import com.component.composite.AcerMantainComposite;
import com.component.leaf.AcerMantainLeaf;
public class ComponentMain {
public static void main(String[] args) {
AcerComponent rootAc = new AcerMantainComposite("中国维修总部");
// 左节点,叶子节点,没有分支了
AcerComponent personLeft = new AcerMantainLeaf("中国区个人代理维修部");
// 右节点,有下属的分公司,不是叶子节点,本身这个节点也是一个维修部
AcerComponent CompositeRight = new AcerMantainComposite("中国维修总部下属的北京维修分部");
// 右节点下的左节点,即北京维修分部下属的一个个人代理部,但是personAcBJ是一个叶子节点,没有下属了
AcerComponent personAcBJ = new AcerMantainLeaf("中国维修总部下属的北京维修分部下属的北京个人代理维修部");
CompositeRight.addMaintainDepartment(personAcBJ);
// 右节点下的右节点,即北京维修分部下属的分公司,不是叶子节点
AcerComponent CompositeAcBJ = new AcerMantainComposite("中国维修总部下属的北京维修分部下属的北京朝阳维修分部");
AcerComponent personAcBJCY = new AcerMantainLeaf("中国维修总部下属的北京维修分部下属的北京朝阳维修分部下属的北京朝阳五里桥个人代理维修部");
CompositeAcBJ.addMaintainDepartment(personAcBJCY);
CompositeRight.addMaintainDepartment(CompositeAcBJ);
rootAc.addMaintainDepartment(personLeft);
rootAc.addMaintainDepartment(CompositeRight);
rootAc.display();
}
}
这是测试类的结构图,用Visio随笔画的,大家看看意思就行
最后就是测试结果了
引用大话设计模式的片段:“当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。”