Java设计模式--组合模式

    xiaoxiao2026-01-13  11

    组合模式

    将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使用户对单个对象和组合对象的使用具有一致性。

    Composite Pattern

    Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

    类图

    模式的结构与使用

    组合方法模式的结构中包括三种角色。 + 抽象组件(Abstract Component):是一个接口(抽象类),该接口(抽象类)定义了个体对象和组合对象需要实现的关于操作其子节点的方法,比如add()、remove()以及getChild()等方法。抽象组件也可以定义个体对象和组合对象用于操作其自身的方法,比如isLeaf()方法等。 + Composite(Composite Node):实现Component接口类的实例,Composite节点不仅实现Component接口,而且可以含有其他Composite节点或Leaf节点的引用。 + Leaf节点(Leaf Node):实现Component接口类的实例,Leaf节点实现Composite接口,不可以含有其他Composite节点或Leaf节点的引用,因此,叶节点在实现Component接口有关操作子节点的方法时,比如add()、remove()和getChild()方法,可让方法抛出一个异常,也可以实现为空操作。

    简单的例子

    Component的接口类MilitaryPerson.java

    package Component; 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); }

    Composite的实现类MilitaryOfficer.java

    package Component; import java.util.Iterator; import java.util.LinkedList; public class MilitaryOfficer implements MilitaryPerson { LinkedList<MilitaryPerson> list; String name; double salary; public 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(person); } @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; } }

    Leaf的实现类MilitarySoldier.java

    package Component; import java.util.Iterator; public class MilitarySoldier implements MilitaryPerson { double salary; String name; public MilitarySoldier(double salary, String name) { this.salary = salary; this.name = name; } @Override public void add(MilitaryPerson person) {} @Override public void remove(MilitaryPerson person) {} @Override public MilitaryPerson getChild(int index) { return null; } @Override public Iterator<MilitaryPerson> getAllChildren() { return null; } @Override public boolean isLeaf() { return true; } @Override public double getSalary() { return salary; } @Override public void setSalary(double salary) { this.salary = salary; } }

    计算工资的工具类ComputerSalary.java

    package Component; import java.util.Iterator; 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; } }

    测试类Application.java

    package Component; public class Application { public static void main(String[] args) { MilitaryPerson 连长 = new MilitaryOfficer("连长", 5000); MilitaryPerson 排长1 = new MilitaryOfficer("一排长", 4000); MilitaryPerson 排长2 = new MilitaryOfficer("二排长", 4000); MilitaryPerson 排长3 = new MilitaryOfficer("三排长", 4000); MilitaryPerson 班长11 = new MilitaryOfficer("一排长", 2000); MilitaryPerson 班长12 = new MilitaryOfficer("二排长", 2000); MilitaryPerson 班长13 = new MilitaryOfficer("三排长", 2000); MilitaryPerson 班长21 = new MilitaryOfficer("一排长", 2000); MilitaryPerson 班长22 = new MilitaryOfficer("二排长", 2000); MilitaryPerson 班长23 = new MilitaryOfficer("三排长", 2000); MilitaryPerson 班长31 = new MilitaryOfficer("一排长", 2000); MilitaryPerson 班长32 = new MilitaryOfficer("二排长", 2000); MilitaryPerson 班长33 = new MilitaryOfficer("三排长", 2000); MilitaryPerson[] 士兵 = new MilitarySoldier[90]; for (int i = 0; i < 士兵.length; i++) { 士兵[i] = new MilitarySoldier(1000, "小兵"); } 连长.add(排长1); 连长.add(排长2); 排长1.add(班长11); 排长1.add(班长12); 排长1.add(班长13); 排长2.add(班长21); 排长2.add(班长22); 排长2.add(班长23); 排长3.add(班长31); 排长3.add(班长32); 排长3.add(班长33); for (int i = 0; i <= 9; i++) { 班长11.add(士兵[i]); 班长12.add(士兵[i + 10]); 班长13.add(士兵[i + 20]); 班长21.add(士兵[i + 30]); 班长22.add(士兵[i + 40]); 班长23.add(士兵[i + 50]); 班长31.add(士兵[i + 60]); 班长32.add(士兵[i + 70]); 班长33.add(士兵[i + 80]); } System.out.println("一排的军饷:" + ComputerSalary.computerSalary(排长1)); System.out.println("一班的军饷:" + ComputerSalary.computerSalary(班长11)); System.out.println("全连的军饷:" + ComputerSalary.computerSalary(连长)); } }

    执行效果图

    组合模式的优点

    组合模式中包含个体对象和组合对象,并形成树形结构,使用户可以方便地处理个体对象和组合对象。组合对象和个体对象实现了相同的接口,用户一般无须区分个体对象和组合对象。当增加新的Composite节点和Leaf节点时,用户的重要代码不需要作出修改,例如,如果增加一个创建企业领导和一般职员的Composite节点和Leaf节点,那么ComputerSalary并不需要修改,就可以计算一个部门的薪水总和。

    适用组合模式的情景

    当想表示对象的部分-整体层次结构。希望用户用一致的方式处理个体对象和组合对象。

    下载源码请到

    MyGitHub

    最新回复(0)