引入
书接上回,我们来聊聊啥是组合模式?
将对象组合成树形结构以表示“部分-整体”的层次结构;
这个模式是关于怎样将对象形成树形结构来表现整体和部分的层次结构的成熟模式。
适合用组合模式的场景
- 当想表示对象的部分-整体层次结构
- 希望用户用一致的方式处理个体对象和组合对象
组合模式的结构
这里拿一个描述队伍结构的例子来举例,它的结构
简单对象和组合对象都是实现抽象组件的接口,组合对象中间又通过一个抽象组件链表来表示它的子树,而叶子节点(简单对象)就不需要这个链表,所以组合对象多一个引用箭头。
抽象组件
import java.util.Iterator;
//根节点
public interface MilitaryPerson {
public void add(MilitaryPerson person);
public void remove(MilitaryPerson person);
public MilitaryPerson getChild(int index);
public Iterator<MilitaryPerson> getAllChildren();
public boolean isLeaf();
public double getSalary();
public void setSalary(double salary);
}
叶子节点
import java.util.Iterator;
//叶子节点
public class MilitarySoldier implements MilitaryPerson{
double salary;
String name;
MilitarySoldier(String name , double salary){
this.name = name;
this.salary = salary;
}
//叶子节点是不实现添加和移除节点的函数
@Override
public void add(MilitaryPerson person) {}
@Override
public void remove(MilitaryPerson person) {}
//返回它的孩子节点为null
@Override
public MilitaryPerson getChild(int index) {
return null;
}
//返回它的孩子节点为null
@Override
public Iterator<MilitaryPerson> getAllChildren() {
return null;
}
//leaf是一个标志位,用来表示是否为叶子节点
@Override
public boolean isLeaf() {
return true;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(double salary) {
this.salary = salary;
}
}
组合对象(子节点)
import java.util.Iterator;
import java.util.LinkedList;
// 组合对象
public class MilitaryOfficer implements MilitaryPerson{
//和简单对象的主要区别就在于组合对象多个一个抽象组件的列表,用来存放它的子树
LinkedList<MilitaryPerson> list;
String name;
double salary;
MilitaryOfficer(String name , double salary){
this.name = name;
this.salary = salary;
list = new LinkedList<MilitaryPerson>();
}
@Override
public void add(MilitaryPerson person) {
list.add(person);
}
@Override
public void remove(MilitaryPerson person) {
list.remove();
}
@Override
public MilitaryPerson getChild(int index) {
return list.get(index);
}
@Override
public Iterator<MilitaryPerson> getAllChildren() {
return list.iterator();
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(double salary) {
this.salary = salary;
}
}
计算函数和应用程序入口
import java.util.Iterator;
public class Application {
public static void main(String[] args) {
//组织新建组件实例
MilitaryPerson companyCommander = new MilitaryOfficer("连长",5000);
MilitaryPerson platoonLeader1 = new MilitaryOfficer("一排长",4000);
MilitaryPerson platoonLeader2 = new MilitaryOfficer("二排长",4000);
MilitaryPerson squadLeader11 = new MilitaryOfficer("一班长",2000);
MilitaryPerson squadLeader12 = new MilitaryOfficer("二班长",2000);
MilitaryPerson squadLeader13 = new MilitaryOfficer("三班长",2000);
MilitaryPerson squadLeader21 = new MilitaryOfficer("一班长",2000);
MilitaryPerson squadLeader22 = new MilitaryOfficer("二班长",2000);
MilitaryPerson squadLeader23 = new MilitaryOfficer("三班长",2000);
MilitaryPerson squadLeader31 = new MilitaryOfficer("一班长",2000);
MilitaryPerson squadLeader32 = new MilitaryOfficer("二班长",2000);
MilitaryPerson squadLeader33 = new MilitaryOfficer("三班长",2000);
MilitaryPerson[] soldier = new MilitarySoldier[60];
for (int i = 0;i<soldier.length;i++){
soldier[i] = new MilitarySoldier("士兵",1000);
}
//建立树形关系
companyCommander.add(platoonLeader1);
companyCommander.add(platoonLeader2);
platoonLeader1.add(squadLeader11);
platoonLeader1.add(squadLeader12);
platoonLeader1.add(squadLeader13);
platoonLeader2.add(squadLeader21);
platoonLeader2.add(squadLeader22);
platoonLeader2.add(squadLeader23);
for (int i =0 ; i<=9;i++){
squadLeader11.add(soldier[i]);
squadLeader12.add(soldier[i+10]);
squadLeader13.add(soldier[i+20]);
squadLeader21.add(soldier[i+30]);
squadLeader22.add(soldier[i+40]);
squadLeader23.add(soldier[i+50]);
}
System.out.println("一排的军饷:"+ComputerSalary.computerSalary(platoonLeader1));
System.out.println("一排一班的军饷:"+ComputerSalary.computerSalary(squadLeader11));
System.out.println("全连的军饷:"+ ComputerSalary.computerSalary(companyCommander));
}
public class ComputerSalary {
public static double computerSalary(MilitaryPerson person){
double sum = 0;
if(person.isLeaf()==true){
sum = sum + person.getSalary();
}//如果为叶子节点,就加上军饷
if(person.isLeaf()==false){
sum = sum + person.getSalary();
Iterator<MilitaryPerson> iterator = person.getAllChildren();
while(iterator.hasNext()){
MilitaryPerson p = iterator.next();
sum = sum + computerSalary(p);
}
}//如果为子节点就加上子节点后遍历它的孩子节点
return sum;
}
}
}
组合模式的优点
- 组合模式中包含个体对象和组合对象,并形成树形结构,使用户可以方便地处理个体对象和组合对象
- 组合对象和个体对象实现了相同的接口,用户一般无须区分个体对象和组合对象
- 当增加新的Composite节点和Leaf节点,用户的主要代码不需要修改(组合比继承的好处就在这里,修改父结点的行为也不会影响到子节点)
总结
多用组合少用继承,现在已经成为一个面向对象的编程准则,不像面向对象语言刚出的时候爆吹继承,现在发现继承的诸多弊端,组合模式这种方式也成为设计层次结构的首选项。