本文源码:GitHub·点这里 || GitEE·点这里

一、生活场景

1、文件系统

下图是常见的计算机文件系统的一部分。

文件系统是一个树结构,树上长有节点。树的节点有两种:

  • 树枝节点

即文件夹,有内部树结构,在图中涂有颜色;

  • 树叶节点

另一种是文件,即树叶节点,没有内部树结构。

2、打印文件树结构

public class C01_InScene {
public static void main(String[] args) {
File file = new File("F:\\tree") ;
fileTree(file, 0);
}
private static void fileTree(File file, int floor) {
// 判断是否存在
if (file.exists()) {
if (floor > 0) {
// 循环打空格
for (int i = 0; i < floor; i++) {
System.out.print(" ");
}
}
if (file.isDirectory()) {
System.out.println("+" + file.getName());
// 列出所有文件及文件夹
File[] files = file.listFiles();
if (null != files) {
// 循环递归
for (File dirFile : files) {
fileTree(dirFile, floor + 1);
}
}
} else {
System.out.println("-" + file.getName());
}
}
}
}

执行效果:+代表文件夹,-代表文件。

+tree
+dir1
+dir2
-dir2Leaf.txt
-leaf1.txt
-leaf2.txt
-OneLeaf.txt
-TwoLeaf.txt

3、组合模式描述

组合模式属于对象的结构模式,有时又叫做“部分——整体”模式。组合模式将对象组织到树结构中,可以用来描述整体与部分的关系。组合模式可以使客户端将单纯元素与复合元素同等看待。

二、组合模式-安全式

1、基础概念

安全式的组合模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。涉及到三个角色:

  • 抽象构件(Component)角色

它给组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。组合对象通常把它所包含的子对象当做类型为Component的对象。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。

  • 树叶构件(Leaf)角色

树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。

  • 树枝构件(Composite)角色

代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及getChild()。

2、模式图解

3、源代码实现

public class C02_Security_Model {
public static void main(String[] args) {
Composite root = new Composite("服装");
Composite composite1 = new Composite("男装");
Leaf manCoat = new Leaf("上衣");
Leaf manBottom = new Leaf("下衣");
composite1.addChild(manCoat);
composite1.addChild(manBottom);
Composite composite2 = new Composite("女装");
Leaf leaf1 = new Leaf("鞋子");
Leaf leaf2 = new Leaf("帽子");
root.addChild(leaf1);
root.addChild(leaf2);
root.addChild(composite1);
root.addChild(composite2);
root.printStruct("");
}
}
// 抽象构件角色类
interface Component {
/*
* 输出组件自身的名称
*/
void printStruct(String preStr);
}
// 树枝构件角色类
class Composite implements Component{
// 用来存储组合对象中包含的子组件对象
private List<Component> childComponents = new ArrayList<Component>();
// 输出对象的名称
private String name;
// 构造方法,传入组合对象的名字
public Composite (String name){
this.name = name;
}
/**
* 聚集管理方法,增加一个子构件对象
* @param child 子构件对象
*/
public void addChild(Component child){
childComponents.add(child);
}
/**
* 聚集管理方法,删除一个子构件对象
* @param index 子构件对象的下标
*/
public void removeChild(int index){
childComponents.remove(index);
}
/**
* 聚集管理方法,返回所有子构件对象
*/
public List getChild(){
return childComponents ;
}
/**
* 输出对象的自身结构
* @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
//先输出自己
System.out.println(preStr+"+"+this.name);
//如果还包含有子组件,那么就输出这些子组件对象
if (this.childComponents != null){
//添加两个空格,表示向后缩进两个空格
preStr = preStr+" ";
//输出当前的子对象:使用函数递归的原理
for (Component c : childComponents) {
c.printStruct(preStr);
}
}
}
}
class Leaf implements Component{
// 输出叶子对象的名称
private String name;
// 构造方法,传入叶子对象的名称
public Leaf (String name){
this.name = name ;
}
/**
* 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
* @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
System.out.println(preStr+"-"+name);
}
}
  • 输出结果
+服装
-鞋子
-帽子
+男装
-上衣
-下衣
+女装

三、组合模式-透明式

1、概念图解

与安全式的组合模式不同的是,透明式的组合模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。

2、源代码实现

public class C03_Transparent_Model {
public static void main(String[] args) {
Component1 root = new Composite1("服装");
Component1 c1 = new Composite1("男装");
Component1 c2 = new Composite1("女装");
Component1 leaf1 = new Leaf1("衬衫");
Component1 leaf2 = new Leaf1("夹克");
Component1 leaf3 = new Leaf1("裙子");
Component1 leaf4 = new Leaf1("套装");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}
abstract class Component1 {
/**
* 输出组件自身的名称
*/
public abstract void printStruct(String preStr);
// 聚集管理方法,增加一个子构件对象
public void addChild(Component1 child){
/**
* 缺省实现,抛出异常,因为叶子对象没有此功能
* 或者子组件没有实现这个功能
*/
throw new UnsupportedOperationException("对象不支持此功能");
}
// 聚集管理方法,删除一个子构件对象
public void removeChild(int index){
/**
* 缺省实现,抛出异常,因为叶子对象没有此功能
* 或者子组件没有实现这个功能
*/
throw new UnsupportedOperationException("对象不支持此功能");
}
// 聚集管理方法,返回所有子构件对象
public List<Component1> getChild(){
/**
* 缺省实现,抛出异常,因为叶子对象没有此功能
* 或者子组件没有实现这个功能
*/
throw new UnsupportedOperationException("对象不支持此功能");
}
}
class Composite1 extends Component1 {
// 用来存储组合对象中包含的子组件对象
private List<Component1> childComponents = new ArrayList<Component1>();
// 输出对象名称
private String name ;
public Composite1 (String name){
this.name = name;
}
/**
* 聚集管理方法,增加一个子构件对象
* @param child 子构件对象
*/
public void addChild(Component1 child){
childComponents.add(child);
}
/**
* 聚集管理方法,删除一个子构件对象
* @param index 子构件对象的下标
*/
public void removeChild(int index){
childComponents.remove(index);
}
// 聚集管理方法,返回所有子构件对象
public List<Component1> getChild(){
return childComponents ;
}
/**
* 输出对象的自身结构
* @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
// 首先输出自己名称
System.out.println(preStr+"+"+this.name);
// 如果还包含有子组件,那么就输出这些子组件对象
preStr = preStr + " ";
if (this.childComponents != null) {
// 添加两个空格,表示向后缩进
for (Component1 c : childComponents) {
////递归输出每个子对象
c.printStruct(preStr);
}
}
}
}
class Leaf1 extends Component1 {
private String name;
public Leaf1 (String name){
this.name = name;
}
/**
* 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
* @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
*/
@Override
public void printStruct(String preStr) {
System.out.println(preStr+"-"+name);
}
}

四、JDK中应用

1、HashMap结构图

2、分层结构

  • interface Map
  • class AbstractMap implements Map
  • HashMap extends AbstractMap implements Map
  • interface Map.Entry
  • Node implements Map.Entry

3、源代码

  • 存储叶子节点
public V put(K var1, V var2) {
return this.putVal(hash(var1), var1, var2, false, true);
}
final V putVal(int var1, K var2, V var3, boolean var4, boolean var5) {
HashMap.Node[] var6 = this.table;
.......
}
  • 存储树枝节点
public void putAll(Map<? extends K, ? extends V> var1) {
this.putMapEntries(var1, true);
}

五、源代码地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

最新文章

  1. 数据分析(9):DataFrame介绍
  2. 核型SVM
  3. 初学javaweb,远离各自框架
  4. AWK处理日志入门(转)
  5. 高性能javascript及页面注意事项
  6. SQLite入门与分析(九)---VACUUM命令分析
  7. Activity一共有以下四种launchMode
  8. BotVS趋势交易策略-MA均线
  9. 【JDK1.8】JDK1.8集合源码阅读——总章
  10. DUEditor的诞生
  11. H5单张、多张图片上传
  12. android 可以精确到秒级的时间选择器
  13. public private protected default
  14. 菜鸟Vue学习笔记(一)
  15. stark组件开发之分页
  16. Peer Programming Project: 4 Elevators Scheduler 附加题 157 165
  17. ECS——安装nginx
  18. Java知多少(97)绘图模式概述
  19. Azure ARM (18) 将Azure RM Manage Disk托管磁盘的Image,跨订阅迁移
  20. 冲刺博客NO.1

热门文章

  1. js方法中参数传过来的值包含括号
  2. 使用Pycharm轻轻松松脱下git版本控制高大上的外衣
  3. JS计算数组的总和
  4. Redis有哪几种数据类型
  5. 《Java基础知识》Java this关键字详解
  6. UWP 打开系统设置面板
  7. Java连载62-使用throws关键字处理异常
  8. docker安装redis 5.0.7并挂载外部配置和数据
  9. asp.net core使用serilog将日志推送到腾讯云日志服务
  10. SpringMVC架构模拟