一、了解组合模式

1.1 什么是组合模式

组合模式允许你将对象组合成树形结构来表现“整体/部分”层次机构。组合能够使客户以一致的方式处理个别对象以及组合对象。

组合模式让我们能够用树形方式创建对象的结构,树里面包含了组合以及个别的对象。

使用组合结构,我们能够把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。

1.2 组合模式组成结构

  • Component :是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理 Component 子部件。
  • Leaf :在组合中表示叶子结点对象,叶子结点没有子结点。
  • Composite :定义有枝节点行为,用来存储子部件,在 Component 接口中实现与子部件有关操作,如增加 (add) 和删除 (remove) 等。

1.3 组合模式 UML 图解

组合包含组件。组件有两种:组合和叶节点元素。组合持有一群孩子,这些孩子可以分别是别的组合或者叶节点元素。当你使用这种方式组织数据的时候,最终会得到树形结构 (由上而下的树形结构),根部是一个组合,而组合的分支逐渐向下延伸,直到叶节点为止。

1.4 组合模式应用场景

  • 想表示对象的部分-整体层次结构(树形结构)。
  • 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

二、组合模式具体应用

2.1 问题描述

打印菜单:通过代码实现打印早、中、晚餐的菜单,列出所有的菜品,并且在晚餐菜单中包含甜品菜单。

2.2 问题树形结构分析图

2.3 使用组合模式设计相关类图

2.4 代码实现

MenuComponent 抽象类

package com.jas.component;/*** @author Jas* @create 2018-01-30 10:23**/
public abstract class MenuComponent {public void add(MenuComponent menuComponent){throw new UnsupportedOperationException();}public void remove(MenuComponent menuComponent){throw new UnsupportedOperationException();}public MenuComponent getChild(int i){throw new UnsupportedOperationException();}public String getName(){throw new UnsupportedOperationException();}public double getPrice(){throw new UnsupportedOperationException();}public void print(){throw new UnsupportedOperationException();}}

组件 MenuItem 类

package com.jas.component;/*** 菜单项类实现,用来封装菜品信息* * getName() 方法返回菜品名字* getPrice() 方法返回菜品价格* print() 输出该菜品的详细信息* * @author Jas* @create 2018-01-30 10:26**/
public class MenuItem extends MenuComponent{String name;double price;public MenuItem(String name, double price){this.name = name;this.price = price;}@Overridepublic String getName() {return name;}@Overridepublic double getPrice() {return price;}@Overridepublic void print() {System.out.print(" " + getName());System.out.println(" " + getPrice());}
}

组件 Menu 类

package com.jas.component;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** 菜单类,* * getName() 方法返回具体菜单名* add(MenuComponent menuComponent) 方法表示添加菜单* remove(MenuComponent menuComponent) 删除一个菜单* getChild(int i) 返回一个指定的菜单* print() 用于输出菜单名和具体菜单菜品信息,也是所有代码中最难理解的一部分* * @author Jas* @create 2018-01-30 10:30**/
public class Menu extends MenuComponent {/** menuComponents 用来保存早中晚的菜单项。 */List<MenuComponent> menuComponents = new ArrayList<>();/** name 表示菜单名 (早中晚甜品)*/String name;public Menu(String name){this.name = name;}@Overridepublic void add(MenuComponent menuComponent) {menuComponents.add(menuComponent);}@Overridepublic void remove(MenuComponent menuComponent) {menuComponents.remove(menuComponent);}@Overridepublic MenuComponent getChild(int i) {return menuComponents.get(i);}@Overridepublic String getName() {return name;}/*** 既可以输出菜单名,也可以输出菜单中的菜品名*/@Overridepublic void print() {System.out.println("\n" + getName());System.out.println("====================");Iterator<MenuComponent> iterator = menuComponents.iterator();while (iterator.hasNext()){MenuComponent menuComponent = iterator.next();menuComponent.print();}}
}

Waitress 类

package com.jas.component;/*** 招待员类* * @author Jas* @create 2018-01-30 10:39**/
public class Waitress {MenuComponent allMenus;public Waitress(MenuComponent allMenus){this.allMenus = allMenus;}public void print(){allMenus.print();}
}

测试类

package com.jas.component;/***测试类* * @author Jas* @create 2018-01-30 10:40**/
public class MenuTestDrive {public static void main(String[] args) {MenuComponent breakfastMenu = new Menu("早餐菜单");MenuComponent lunchMenu = new Menu("午餐菜单");MenuComponent dinnerMenu = new Menu("晚餐菜单");MenuComponent dessertMenu = new Menu("甜品菜单");/** 顶层菜单*/MenuComponent allMenus = new Menu("ALL MENUS LIST");breakfastMenu.add(new MenuItem("包子", 1.0));breakfastMenu.add(new MenuItem("豆浆",2.0));lunchMenu.add(new MenuItem("西红柿盖浇饭", 10.0));lunchMenu.add(new MenuItem("西红柿鸡蛋面",10.0));dinnerMenu.add(new MenuItem("热狗", 15.0));dessertMenu.add(new MenuItem("苹果派", 5.0));allMenus.add(breakfastMenu);allMenus.add(lunchMenu);allMenus.add(dinnerMenu);/** 将甜品菜单添加在晚餐菜单中*/dinnerMenu.add(dessertMenu);Waitress waitress = new Waitress(allMenus);waitress.print();}
}/*** 输出* ALL MENUS LIST* ====================** 早餐菜单* ====================* 包子 1.0* 豆浆 2.0** 午餐菜单* ====================* 西红柿盖浇饭 10.0* 西红柿鸡蛋面 10.0** 晚餐菜单* ====================*  热狗 15.0**  甜品菜单* ====================*  苹果派 5.0* */

三、组合模式总结

3.1 组合模式优缺点

优点

  • 高层模块调用简单。
  • 节点可自由增加。

缺点

在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了面对抽象编程和依赖倒置原则。

3.2 组合模式知识点总结

  • 组合模式提供一个结构,可同时包容个别对象和组合对象。
  • 组合模式允许客户对个别对象以及组合对象一视同仁。
  • 组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
  • 在使用组合模式时,要多加考虑方式,有的时候可以与迭代器模式配合使用。

PS:点击了解更多设计模式 http://blog.csdn.net/codejas/article/details/79236013

参考文献

《Head First 设计模式》

Java 设计模式之组合模式相关推荐

  1. java设计模式之组合模式(树形层级)

    java设计模式之组合模式 学习难度:★★★☆☆,使用频率:★★★★☆]  树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式来 ...

  2. Java设计模式之组合模式详解

    文章目录 详解Java设计模式之组合模式 案例引入 组合模式 定义 模式类图结构 相关角色 典型代码 案例分析 类图设计 实例代码 结果分析 JavaJDK中的组合模式 透明组合模式 安全组合模式 组 ...

  3. Java设计模式之组合模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  4. 【Java设计模式】组合模式

    转自:  https://blog.csdn.net/qq_42322103/article/details/95457321 漫谈网站优化提速: https://blog.csdn.net/mete ...

  5. Java设计模式中组合模式是什么/树形结构怎么组合或显示存储,编程怎么实现树形结构

    继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用! 5.7 组合模式 5.7.1 概述 又名整体模式,是用于把一组相似的对象当作一个单一的对象 依据树形结构 ...

  6. java设计模式用组合模式实现树形结构

    现有如下需求,某公司的机构: +公司 +分公司 +本地分公司 -呼和浩特 +包头 -昆区办事处 -青山办事处 +外地分公司 +总部 -人事处 +办公室 +财务处 实现思路: 抽象组合类,叶子类,根类 ...

  7. (设计模式十一)java设计模式之组合模式

    定义: 组合模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它创建了对象组的树形结构.这种模式创建了一个包含 ...

  8. java设计模式之组合模式(Composite)

    在现实生活中,存在很多"部分-整体"的关系,例如,大学中的部门与学院.总公司中的部门与分公司.学习用品中的书与书包.生活用品中的衣月艮与衣柜以及厨房中的锅碗瓢盆等.在软件开发中也是 ...

  9. Java设计模式之组合模式(透明组合模式,安全组合模式)

    一.概述 组合多个对象形成树形结构以表示具有部分-整体关系的层次结构,可以让客户端统一对待单个对象和组合对象. 组合模式关注那些包含叶子构件和容器构件的结构以及它们的组织形式,在叶子构件中不包含成员变 ...

最新文章

  1. OpenStack云计算快速入门教程
  2. 【PPT 下载】神策 2017 数据驱动大会干货限时分享!
  3. Arrays.copyOf()、Arrays.copyOfRange()与System.arraycopy()用法
  4. Linux IP 配置
  5. rabbitmq的安装和使用
  6. (转)无特征过狗一句话猥琐思路
  7. BluePrism初尝2
  8. Java连续获取两个输入,java 获取控制台的输入的两个方法
  9. 佳恩半导体完成数千万A轮融资
  10. 光子 量子 DNA计算机的发展情况,CPU的发展与量子计算机.pdf
  11. jqgrid for asp.net 遍历所有列rowObject时不用输入编号
  12. 06-ICMP: Internet 控制报文协议
  13. Struts2框架的概念及使用方法
  14. Linux基础——脚本
  15. vue json对象转数组
  16. 1万条数据大概占多大空间_国漫丨2019年上半年漫画数据报告
  17. 辽宁省全国计算机 考点 社会,辽宁2018年9月全国计算机二级考试报考地点
  18. Decoder原理和浅解
  19. fMRI Tutorial:FSL处理功能核磁共振数据
  20. 20170118修改商品流水

热门文章

  1. Session一致性的解决方案
  2. 牛客题霸 NC24 删除有序链表中重复的元素-II
  3. 牛客题霸 SQL4 查找所有已经分配部门的员工的last_name和first_name以及dept_no
  4. sqoop1.4.5 导入 hive IOException running import job: java.io.IOException: Hive exited with status 1
  5. The constructor BASE64Decoder() is not accessible due to restriction on required library
  6. SpringSide 4 QuickStart运行Demo
  7. JavaScript学习笔记04【高级——DOM和事件的简单学习、BOM对象】
  8. 计算机组成原理 第三章【存储系统】课后作业解析【MOOC答案】
  9. Android 短视频拍摄、拍照滤镜 第三方库SDK
  10. eclipse 设置豆沙绿保护色,保护眼睛