深度解析设计模式之组合模式

开发 前端
组合模式(Composite Pattern),又叫部分整体模式,依据树形结构来组合对象,用来表示部分以及整体层次。

[[424219]]

一、介绍

组合模式(Composite Pattern),又叫部分整体模式,依据树形结构来组合对象,用来表示部分以及整体层次。

组合模式 一般用来描述整体与部分的关系,它将对象组织到树形结构中,最顶层的节点称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。如下图所示:

在组合模式中,会把树枝节点和叶子节点认为是同一种数据类型(用同一接口定义),让它们具备一致行为。

这样,整个树形结构中的对象都是同一种类型,带来的一个好处就是客户无需辨别 树枝节点还是叶子节点,而是可以直接进行操作,给客户使用带来极大的便利。

从设计的角度看,组合模式涉及到三个角色:

抽象根节点:它是一个抽象接口,定义了算法;

具体节点:实现或继承自抽象根节点,完成具体算法操作;

客户端:客户类提出使用具体类的请求;

二、示例

下面,我们拿学校的组织架构为例,比如说一个学校,包含了后勤部、网络部、教学部、保卫部、分校等部门组成,每一个分校,同样具有后勤部、网络部这些。既然这些部门都是学校的部门,基本的操作应该都是一样的,我们可以将所有的部门都拉入学校属性。

用类图表示如下:

实现过程如下!

  1. /** 
  2.  * 学校接口 
  3.  */ 
  4. public interface School { 
  5.  
  6.     /** 
  7.      * 添加分校或者部门 
  8.      * @param school 
  9.      */ 
  10.     void addPart(School school); 
  11.  
  12.     /** 
  13.      * 移除分校或者部门 
  14.      * @param school 
  15.      */ 
  16.     void removePart(School school); 
  17.  
  18.     /** 
  19.      * 展示分校或者部门信息 
  20.      */ 
  21.     void displayPart(); 

然后,创建一个学校具体实现类ConcreteSchool,可以是总校,也可以是分校,如下:

  1. /** 
  2.  * 具体学校,可以是总校,也可以是分校 
  3.  */ 
  4. public class ConcreteSchool implements School { 
  5.  
  6.     private String name;//名称 
  7.  
  8.     private List<School> partList = new ArrayList<>(); 
  9.  
  10.     public ConcreteSchool(String name) { 
  11.         this.name = name
  12.     } 
  13.  
  14.     @Override 
  15.     public void addPart(School school) { 
  16.         partList.add(school); 
  17.     } 
  18.  
  19.     @Override 
  20.     public void removePart(School school) { 
  21.         partList.remove(school); 
  22.     } 
  23.  
  24.     /** 
  25.      * 学校查看部门信息 
  26.      */ 
  27.     @Override 
  28.     public void displayPart() { 
  29.         for (School school : partList) { 
  30.             school.displayPart(); 
  31.         } 
  32.  
  33.     } 

接着,创建两个具体的部门,网络部门InternetDepartment、安全部门SecurityDepartment,代码如下:

  1. /** 
  2.  * 网络部门 
  3.  */ 
  4. public class InternetDepartment implements School { 
  5.  
  6.     private String name;//名称 
  7.  
  8.     public InternetDepartment(String name) { 
  9.         this.name = name
  10.     } 
  11.  
  12.     @Override 
  13.     public void addPart(School school) {} 
  14.  
  15.     @Override 
  16.     public void removePart(School school) {} 
  17.  
  18.     @Override 
  19.     public void displayPart() { 
  20.         System.out.println("我是" + name + ",负责学校的网络管理"); 
  21.     } 
  1. /** 
  2.  * 安全部门 
  3.  */ 
  4. public class SecurityDepartment implements School { 
  5.  
  6.     private String name;//名称 
  7.  
  8.     public SecurityDepartment(String name) { 
  9.         this.name = name
  10.     } 
  11.  
  12.     @Override 
  13.     public void addPart(School school) {} 
  14.  
  15.     @Override 
  16.     public void removePart(School school) {} 
  17.  
  18.     @Override 
  19.     public void displayPart() { 
  20.         System.out.println("我是" + name + ",负责学校的安全工作"); 
  21.     } 

最后,编写一个测试类,如下:

  1. public class CompositeClient { 
  2.  
  3.     public static void main(String[] args) { 
  4.         //总校部门 
  5.         ConcreteSchool rootSchool = new ConcreteSchool("总校"); 
  6.         rootSchool.addPart(new InternetDepartment("总校网络部门")); 
  7.         rootSchool.addPart(new SecurityDepartment("总校安全部门")); 
  8.  
  9.         //分校部门 
  10.         ConcreteSchool branchSchool = new ConcreteSchool("分校"); 
  11.         branchSchool.addPart(new InternetDepartment("分校网络部门")); 
  12.         branchSchool.addPart(new SecurityDepartment("分校安全部门")); 
  13.  
  14.         rootSchool.addPart(branchSchool); 
  15.         rootSchool.displayPart();//展示信息 
  16.     } 

输出结果:

  1. 我是总校网络部门,负责学校的网络管理 
  2. 我是总校安全部门,负责学校的安全工作 
  3. 我是分校网络部门,负责学校的网络管理 
  4. 我是分校安全部门,负责学校的安全工作 

从上面的例子,可以很清晰看到类的层次关系,所有的具体对象当作一个单一的对象School来处理。

三、应用

在 Java 的 GUI 容器组件中,就用到了组合模式,所有的子类组件,都可以看作为容器对象。

当然,还有我们使用的 Mybatis 在处理动态 SQL 节点时,也应用到了组合设计模式,Mybatis 会将映射配置文件中定义的动态 SQL 节点、文本节点等解析成对应的 SqlNode 实现,并形成树形结构。

四、总结

当想表达对象的部分-整体的层次结构时,推荐采用组合模式进行设计。

五、参考

1、java的架构师技术栈 - 23种设计模式之组合模式

2、菜鸟教程 -组合模式

 

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2012-04-12 09:38:21

JavaScript

2013-11-26 15:48:53

Android设计模式SDK

2020-08-21 07:23:50

工厂模式设计

2021-06-09 08:53:34

设计模式策略模式工厂模式

2012-02-29 09:41:14

JavaScript

2023-09-04 13:14:00

装饰器设计模式

2021-06-16 08:56:06

模版方法模式设计模式行为型设计模式

2021-12-24 07:50:45

责任链模式设计

2021-06-29 08:54:23

设计模式代理模式远程代理

2015-09-08 13:39:10

JavaScript设计模式

2012-01-13 15:59:07

2020-12-01 07:16:05

重学设计模式

2021-01-21 05:34:14

设计模式建造者

2021-03-05 07:57:41

设计模式桥接

2010-04-19 09:30:00

工厂模式PHP设计模式

2012-07-11 08:51:51

设计模式

2016-03-28 10:23:11

Android设计单例

2010-03-25 08:52:30

PHP设计模式代理模式

2022-03-25 11:01:28

Golang装饰模式Go 语言

2021-06-22 15:27:13

设计模式迭代器模式Java
点赞
收藏

51CTO技术栈公众号