本文源码: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

Java描述设计模式(10):组合模式的更多相关文章

  1. C#设计模式(10)——组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  2. C#设计模式(10)——组合模式(Composite Pattern)(转)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  3. C#设计模式(10)——组合模式

    一.概念 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦. 二.组 ...

  4. 基于JAVA的设计模式之组合模式

    概念 将所有对象组合成一种树形结构,有分支节点.叶子节点,分支节点可以有自己的子节点,子节点可以是分支节点.叶子节点,可以进行增删的操作,而叶子节点不可以.比如文件夹就是一个分支节点,而文件就是一个叶 ...

  5. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  6. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  7. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  8. C#设计模式:组合模式(Composite Pattern)

    一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ...

  9. 设计模式之组合模式——Java语言描述

    组合模式又叫做部分整体模式,适用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次 介绍 意图 将对象组合成树形结构以表示"部分-整体" ...

随机推荐

  1. exports、module.exports 和 export、export default

    先了解他们的使用范围. require: node 和 es6 都支持的引入export / import : 只有es6 支持的导出引入module.exports / exports: 只有 no ...

  2. python并发之多进程

    #mutiprocessing模块 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Pytho ...

  3. getX,getY,getScrollX,getScrollY,ScrollTo(),ScrollBy()辨析

    前言:前两天看了自定义控件,其中有一些东西我觉得有必要深入理解一下 以下图为例: getX(),getY()返回的是触摸点A相对于view的位置 getRaw(),getRawY()返回的是触摸点B相 ...

  4. 《Java基础知识》Java访问修饰符(访问控制符)

    Java 通过修饰符来控制类.属性和方法的访问权限和其他功能,通常放在语句的最前端.例如: public class className { // body of class } private bo ...

  5. [ASP.NET Core 3框架揭秘] 文件系统[3]:物理文件系统

    ASP.NET Core应用中使用得最多的还是具体的物理文件,比如配置文件.View文件以及作为Web资源的静态文件.物理文件系统由定义在NuGet包"Microsoft.Extension ...

  6. HCTF_2018-Writeup【web题】

    HCTF_2018-Writeup 赛题来自:BUUCTF By:Mirror王宇阳 WarmUp: 打开赛题的页面源码(F12) <!DOCTYPE html> <html lan ...

  7. RAC修改字符集

    字符集修改做过几次了,这次感觉还是有点不顺,走了弯路,再记一遍[概况]准备搭建RAC+RAC DG,发现两端字符集不大一致,担心到时出问题. [目标]将备库NLS_NCHAR_CHARACTERSET ...

  8. 《Hands-On System Programming with Go》之写文件的代码模板

    使用了buffer,这个神奇东东. var w io.WriteCloser // initialise writer defer w.Close() b := bufio.NewWriter(w) ...

  9. OS之进程和线程

    1. 线程是程序执行流的最小单元. 一个标准的线程由线程ID,当前指令指针PC,寄存器集合和堆栈组成. 2. 通常意义上,一个进程由一个到多个线程组成,各个线程之间共享程序的的内存空间,包括代码段.数 ...

  10. Leetcode题解 - 树、DFS部分简单题目代码+思路(700、671、653、965、547、473、46)

    700. 二叉搜索树中的搜索 - 树 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 NULL. 思路: 二 ...