1 基础知识
1.1 标准定义
组合(Composite)模式标准定义:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
1.2 分析和说明
组合(Composite)模式属于结构型设计模式。它将对象组合成树形结构以表示“整体-部分”的层次结构,定义了包含基本对象和组合对象的类层次结构,使得用户对单个对象和组合对象的使用具有一致性。组合模式就是一个处理对象的树结构的模式。组合模式把部分与整体的关系用树结构表示出来,使得客户端把一个个单独的成分对象和由他们复合而成的组合对象同等看待。
组合(Composite)模式结构如图1所示。其角色包括抽象构件(Component)角色、树枝构件(Composite)角色和树叶构件(Leaf)角色。
图1 组合模式结构
抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。组合对通常把它所包含的子对象当作类型为Component的对象。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。为用户操作Leaf类和Composite类提供一致的方法,它主要定义了Operation(),Add(Component),Remove(Component),GetChild(int)几个方法,其中,Add(Component),Remove(Component),GetChild(int)的责任是对“整体”(Composite类)进行操作;Operation()是“部分”(Leaf类)和“整体”(Composite类)都需要的方法。
树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及components()的声明。除拥有Operation()方法外,还有“整体”类操作的方法,比如Add(Component),Remove(Component),GetChild(int)。Composite 对象由Composite对象和Leaf对象聚合而成,既可以包含“部分”,也可以包含“整体”。
树叶构件(Leaf)角色:树叶对象是没下级子对象的对象,定义出参加组合的原始对象的行为。它拥有Opertion()方法即可满足用户需求的操作。
2 应用场景举例
比如团队(组织)是一个总体的抽象类。集团公司、公司、工厂、部门、班组、项目组是一个团队,都可以继承团队。但是团队本身也是有层次结构的。比如我们要构架一个软件公司,就要这样先形成公司,在形成公司下面的部门,接着形成部门下面的项目组。如果构架一个工厂性质的公司,那在形成完公司根节点后开始形成公司下属的工厂,在工厂下面再形成车间。实现用例图见图2所示。
图2 组合模式用例图
在这里可以把抽象组织(AbstractOrganization)理解为抽象构件(Component)角色。公司(Corporation)、工厂(Factory)、部门(Department)理解为树枝构件(Composite)角色,在其下面还有组织。车间(Workshop)和项目组(WorkTeam)理解为树叶构件(Leaf)角色,在其下面已经没有组织了。而其结构类图如图3所示。公司类(Corporation)、工厂类(Factory)、部门类(Department)、车间类(Workshop)和项目组类(WorkTeam)全部都继承抽象组织类(AbstractOrganization)。
图3 组合模式类图
组合模式实现的顺序图如图4所示,实现顺序描述:
①-⑥都是新建对象,分别为Corporation对象、deaprt1对象、deaprt2对象、deaprt3对象、team1对象和team2对象。
⑦-⑨是把deaprt1对象、deaprt2对象和deaprt3对象插入到Corporation对象下,作为Corporation对象的下级子对象。
⑩-⑩是把team1对象和team2对象插入到deaprt1对象下,作为deaprt1对象的下级子对象。
图4 组合模式实现顺序图
在一个公司组织机构中,公司下面有部门,部门下面有项目组。如果要形成一个公司组织,先创建公司根节点,然后创建公司下属的部门子节点。有的部门下面还有项目组,接着可以在部门节点下面创建项目组孙节点。
3.Java的实现程序代码
Java程序实现主要包括AbstractOrganization抽象类文件,Corporation类文件,Department类文件,Factory类文件,Workshop类文件和WorkTeam类文件等6个文件。其关系如图3所示。下面分别列出这6个文件的程序代码,最后列出测试代码并显示输出结果。
AbstractOrganization抽象类程序代码清单01所示。
程序代码清单01
public abstract class AbstractOrganization { protected String organizationName; protected String organizationType; public AbstractOrganization(String name) { organizationName = name; } public void add(AbstractOrganization organization) { }; public void remove(AbstractOrganization organization) { }; public void showOrganizationStructure(String parentName) { } public String getOrganizationName() { return organizationName; } public void setOrganizationName(String organizationName) { this.organizationName = organizationName; } } |
Corporation具体类,Department具体类和Factory具体类继承AbstractOrganization抽象类,其程序代码清单02所示。
程序代码清单02
public class Corporation extends AbstractOrganization { private List<AbstractOrganization> componentList = new ArrayList<AbstractOrganization>(); public Corporation(String name) { super(name); organizationType = "Corporation"; } public void add(AbstractOrganization organization) { componentList.add(organization); } public void showOrganizationStructure(String parentName) { String organizationName = this.getOrganizationName(); System.out.println(parentName + organizationName); for (int i = 0; i < componentList.size(); i++) { AbstractOrganization organization = componentList.get(i); organization.showOrganizationStructure(parentName + organizationName + "——"); } } } public class Department extends AbstractOrganization { private List<AbstractOrganization> componentList = new ArrayList<AbstractOrganization>(); public Department(String name) { super(name); organizationType = "Department"; } public void add(AbstractOrganization organization) { componentList.add(organization); } public void showOrganizationStructure(String parentName) { String organizationName = this.getOrganizationName(); System.out.println(parentName + organizationName); for (int i = 0; i < componentList.size(); i++) { AbstractOrganization organization = componentList.get(i); organization.showOrganizationStructure(parentName + organizationName + "——"); } } } public class Factory extends AbstractOrganization { private List<AbstractOrganization> componentList = new ArrayList<AbstractOrganization>(); public Factory(String name) { super(name); organizationType = "Factory"; } public void add(AbstractOrganization organization) { componentList.add(organization); } public void showOrganizationStructure(String parentName) { String organizationName = this.getOrganizationName(); System.out.println(parentName + organizationName); for (int i = 0; i < componentList.size(); i++) { AbstractOrganization organization = componentList.get(i); organization.showOrganizationStructure(parentName + organizationName + "——"); } } } |
Workshop具体类和WorkTeam具体类继承AbstractOrganization抽象类,其程序代码清单03所示。
程序代码清单03
public class Workshop extends AbstractOrganization { public Workshop(String name) { super(name); organizationType = "Workshop"; } public void add(AbstractOrganization c) { System.out.println("这是叶子节点,下面没有内容"); } public void showOrganizationStructure(String parentName) { String organizationName = this.getOrganizationName(); System.out.println(parentName + organizationName); } } public class WorkTeam extends AbstractOrganization { public WorkTeam(String name) { super(name); organizationType = "WorkTeam"; } public void add(AbstractOrganization c) { System.out.println("这是叶子节点,下面没有内容"); } public void showOrganizationStructure(String parentName) { String organizationName = this.getOrganizationName(); System.out.println(parentName + organizationName); } } |
组合模式测试程序的代码清单04如下:
程序代码清单04
public class Client { public static void scene1() { // 场景1,形成公司-部门-项目组的公司结构 AbstractOrganization corporation = new Corporation("公司A"); AbstractOrganization depart1 = new Department("部门1"); AbstractOrganization depart2 = new Department("部门2"); AbstractOrganization depart3 = new Department("部门3"); corporation.add(depart1); corporation.add(depart2); corporation.add(depart3); AbstractOrganization team1 = new WorkTeam("项目组1"); AbstractOrganization team2 = new WorkTeam("项目组2"); depart1.add(team1); depart1.add(team2); corporation.showOrganizationStructure(""); } public static void scene2() { // 场景2,形成公司-工厂-车间的工厂结构 AbstractOrganization corporation = new Corporation("公司A"); AbstractOrganization factory1 = new Factory("工厂1"); AbstractOrganization factory2 = new Factory("工厂2"); AbstractOrganization factory3 = new Factory("工厂3"); corporation.add(factory1); corporation.add(factory2); corporation.add(factory3); AbstractOrganization team1 = new Workshop("车间1"); AbstractOrganization team2 = new Workshop("车间2"); factory1.add(team1); factory1.add(team2); corporation.showOrganizationStructure(""); } public static void main(String[] args) { scene1(); System.out.println(); scene2(); } } |
组合模式测试类输出结果如下所示:
公司A 公司A——部门1 公司A——部门1——项目组1 公司A——部门1——项目组2 公司A——部门2 公司A——部门3公司A 公司A——工厂1 公司A——工厂1——车间1 公司A——工厂1——车间2 公司A——工厂2 公司A——工厂3 |
参考链接
7种结构型模式:
Gof23种设计模式(6)——适配器模式(Adapter)
Gof23种设计模式(7)——桥接模式(Bridge)
Gof23种设计模式(8)——组合模式(Composite)
Gof23种设计模式(9)——装饰器模式(Decorator)
Gof23种设计模式(10)——外观模式(Facade)
Gof23种设计模式(11)——享元模式(Flyweight)
Gof23种设计模式(12)——代理模式(Proxy)
Gof23种设计模式 —— 结构型模式总结和比较
回到总目录:Gof23种设计模式(全解析)
(转载自微信公众号:架构设计模式)