组合模式的定义
定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有抑制性。
通用类图如下:
![](https://img.haomeiwen.com/i4259109/5bade98e8f40ab2f.png)
角色说明
-
Component抽象构件角色
定义参加组合对象的公共方法和属性。可以定义一些默认的行为或者属性
-
Leaf叶子构件
叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
-
Composite树枝构件
树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
通用源码
抽象构件
public abstract class Component {
//个体和整体都具有的共享
public void doSomething(){
//编写业务逻辑
}
}
树枝构件
public class Composite extends Component {
//构件容器
private ArrayList<Component> componentArrayList = new ArrayList<Component>();
//增加一个叶子构件或树枝构件
public void add(Component component){
this.componentArrayList.add(component);
}
//删除一个叶子构件或树枝构件
public void remove(Component component){
this.componentArrayList.remove(component);
}
//获得分支下的所有叶子构件和树枝构件
public ArrayList<Component> getChildren(){
return this.componentArrayList;
}
}
树叶构件
public class Leaf extends Component {
/*
* 可以覆写父类方法
* public void doSomething(){
*
* }
*/
}
场景类
public class Client {
public static void main(String[] args) {
//创建一个根节点
Composite root = new Composite();
root.doSomething();
//创建一个树枝构件
Composite branch = new Composite();
//创建一个叶子节点
Leaf leaf = new Leaf();
//建立整体
root.add(branch);
branch.add(leaf);
}
//通过递归遍历树
public static void display(Composite root){
for(Component c:root.getChildren()){
if(c instanceof Leaf){ //叶子节点
c.doSomething();
}else{ //树枝节点
display((Composite)c);
}
}
}
}
组合模式的应用
优点
-
高层模块调用简单
一个树形结构中所有的节点都是Component,局部和整体对调用者来说没有任何区别,也就是,高层模块不必关系自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
-
节点自由增加
使用了组合莫时候,如果想增加一个树枝节点、树叶节点都很容易。
缺点
组合模式有个非常明显的缺点,直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。
使用场景
- 维护和展示部分——整体关系的场景,如树形菜单、文件和文件夹管理。
- 从一个整体中能够独立出部分模块或功能的场景。
组合模式的两种实现
组合模式有两种不同的实现:透明模式和安全模式
透明模式:把用来组合使用的方法放到抽象类中,比如add()
、remove()
以及getChildren()
方法,不管叶子对象还是树枝都有相同的结构,通过判断getChildren()
的返回值来确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题,不建议
安全模式:把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全。
安全组合模式的示例
用组合模式来表示一个公司的组织架构
类图如下:
![](https://img.haomeiwen.com/i4259109/13d2c7a143194b0c.png)
抽象构件
public abstract class Corp {
//公司每个人都有名称
private String name = "";
//公司每个人都职位
private String position = "";
//公司每个人都有薪水
private int salary =0;
//记录当前节点的父节点
private Corp parent = null;
public Corp(String name,String position,int salary){
this.name = name;
this.position = position;
this.salary = salary;
}
//获得员工信息
public String getInfo(){
String info = "";
info = "姓名:" + this.name;
info = info + "\t职位:"+ this.position;
info = info + "\t薪水:" + this.salary;
return info;
}
//设置父节点
protected void setParent(Corp parent){
this.parent = parent;
}
//得到父节点
public Corp getParent(){
return this.parent;
}
}
树枝构件
public class Branch extends Corp {
//领导下边有哪些下级领导和小兵
ArrayList<Corp> subordinateList = new ArrayList<Corp>();
//构造函数是必需的
public Branch(String name,String position,int salary){
super(name,position,salary);
}
//增加一个下属,可能是小头目,也可能是个小兵
public void addSubordinate(Corp corp) {
corp.setParent(this); //设置父节点
this.subordinateList.add(corp);
}
//我有哪些下属
public ArrayList<Corp> getSubordinate() {
return this.subordinateList;
}
}
树叶节点
public class Leaf extends Corp {
//就写一个构造函数,这个是必需的
public Leaf(String name,String position,int salary){
super(name,position,salary);
}
}
场景类
public class Client {
public static void main(String[] args) {
compositeCorpTree();
}
public static Branch compositeCorpTree(){
Branch root = new Branch("王大麻子", "总经理", 100000);
//产生三个部门经理,也是分枝节点
Branch developDep = new Branch("刘", "研发部门经理", 2000);
Branch salesDep = new Branch("王", "销售部经理", 3000);
Branch financeDep = new Branch("高", "财务部经理", 4000);
Branch firstDevGroup = new Branch("阳伞", "开发一组组长", 5);
Branch secondDevGroup = new Branch("san", "开发二组组长", 5);
//小兵
Leaf a = new Leaf("a", "开发人员", 10);
Leaf b = new Leaf("b", "开发人员", 10);
Leaf c = new Leaf("c", "开发人员", 10);
Leaf d = new Leaf("d", "开发人员", 10);
Leaf e = new Leaf("e", "开发人员", 10);
Leaf f = new Leaf("f", "开发人员", 10);
Leaf g = new Leaf("g", "开发人员", 10);
Leaf h = new Leaf("h", "销售人员", 10);
Leaf i = new Leaf("i", "销售人员", 10);
Leaf j = new Leaf("g", "财务人员", 10);
Leaf k = new Leaf("k", "CEO秘书", 10);
Leaf zhengLaoLiu = new Leaf("正老刘", "研发部副总", 1023);
//组织关系
root.addSubordinate(developDep);
root.addSubordinate(salesDep);
root.addSubordinate(financeDep);
root.addSubordinate(k);
developDep.addSubordinate(firstDevGroup);
developDep.addSubordinate(secondDevGroup);
developDep.addSubordinate(zhengLaoLiu);
firstDevGroup.addSubordinate(a);
firstDevGroup.addSubordinate(b);
firstDevGroup.addSubordinate(c);
secondDevGroup.addSubordinate(d);
secondDevGroup.addSubordinate(e);
secondDevGroup.addSubordinate(g);
salesDep.addSubordinate(h);
salesDep.addSubordinate(i);
financeDep.addSubordinate(j);
System.out.println(root.getInfo());
//打印整个树形
getAllSubordinateInfo(root.getSubordinate());
return root;
}
private static void getAllSubordinateInfo(List<Corp> subordinateList){
int length = subordinateList.size();
for (int i = 0; i < length; i++) {
Corp o = subordinateList.get(i);
System.out.println(o.getInfo());
if (o instanceof Branch) {
Branch branch = (Branch)o;
//递归调用其子节点
getAllSubordinateInfo(branch.getSubordinate());
}
}
}
}
透明组合模式的示例
类图如下:
![](https://img.haomeiwen.com/i4259109/356170d421b5bdbb.png)
抽象组件
public abstract class Component {
/**
* 个体和整体都具有的共享
*/
public abstract void doSomething();
/**
* 增加一个叶子构件或树枝构件
* @param component
*/
public abstract void add(Component component);
/**
* 删除一个叶子构件或树枝构件
* @param component
*/
public abstract void remove(Component component);
/**
* 获得分枝下的所有叶子构件或树枝构件
* @return
*/
public abstract List<Component> getChildren();
}
树枝
public class Composite extends Component{
List<Component> subordinateList = new ArrayList<>();
@Override
public void doSomething() {
}
@Override
public void add(Component component) {
this.subordinateList.add(component);
}
@Override
public void remove(Component component) {
this.subordinateList.remove(component);
}
@Override
public List<Component> getChildren() {
return this.subordinateList;
}
}
树叶
public class Leaf extends Component{
@Override
public void doSomething() {
}
@Deprecated
@Override
public void add(Component component) throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public void remove(Component component) throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public List<Component> getChildren() throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
}
网友评论