研磨设计模式day13组合模式

news2024/9/23 23:31:03

目录

场景

不用模式实现 

代码实现 

有何问题 

解决方案

代码改造 

组合模式优缺点

思考 

何时选用


场景

不用模式实现 

代码实现 

叶子对象

package day14组合模式;

/**
 * 叶子对象
 */
public class Leaf {
    /**
     * 叶子对象的名字
     */
    private String name = "";

    /**
     * 构造方法,传入叶子对象的名字
     */
    public Leaf(String name){
        this.name = name;
    }

    /**
     * 输出叶子对象的结构
     */
    public void printStruct(String preStr){
        System.out.println(preStr + "_" + name);
    }
}

组合对象

package day14组合模式;

import java.util.ArrayList;
import java.util.Collection;

/**
 * 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
 * 由于类型不同,需要分开记录
 */
public class Composite {
    /**
     * 用来记录包含的其他组合对象
     */
    private Collection<Composite> childComposite = new ArrayList<>();

    /**
     * 用来记录包含的其他叶子对象
     */
    private Collection<Leaf> childLeaf = new ArrayList<>();

    /**
     * 组合对象的名字
     */
    private String name = "";
    /**
     * 构造方法
     */
    public Composite(String name){
        this.name = name;
    }

    /**
     * 向组合对象加入被它包含的其他组合对象
     * @param c 被它包含的其他组合对象
     */
    public void addComposite(Composite c){
        this.childComposite.add(c);
    }

    /**
     * 向组合对象加入被它包含的叶子对象
     * @param leaf 被它包含的叶子对象
     */
    public void addLeaf(Leaf leaf){
        this.childLeaf.add(leaf);
    }

    /**
     * 输出组合对象自身的结构
     */
    public void printStruct(String prestr){
        // 先把自己输出去
        System.out.println(prestr + "+" + this.name);
        // 然后添加一个空格,表示向后缩进一个空格,输出自己包含的叶子对象
        prestr += " ";
        for (Leaf leaf : childLeaf) {
            leaf.printStruct(prestr);
        }
        // 输出当前对象的子对象了
        for (Composite c : childComposite) {
            // 递归输出每个子对象
            c.printStruct(prestr);
        }
    }
}

Client

package day14组合模式;

public class Client {
    public static void main(String[] args) {
        // 定义所有的组合对象
        Composite root = new Composite("服装");
        Composite c1 = new Composite("男装");
        Composite c2 = new Composite("女装");

        // 定义所有的叶子对象
        Leaf leaf1 = new Leaf("衬衣");
        Leaf leaf2 = new Leaf("夹克");
        Leaf leaf3 = new Leaf("裙子");
        Leaf leaf4 = new Leaf("套装");

        // 按照树的结构来组合 组合对象和叶子对象
        root.addComposite(c1);
        root.addComposite(c2);
        c1.addLeaf(leaf1);
        c1.addLeaf(leaf2);
        c2.addLeaf(leaf3);
        c2.addLeaf(leaf4);

        // 调用跟对象的输出功能来输出整棵树
        root.printStruct("");
    }
}

有何问题 

必须区分组合对象和叶子对象,并进行有区别的对待

解决方案

组合模式

定义:

思路:将组合对象和叶子对象统一起来。通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就统一起来了。

代码改造 

抽象父组件对象

package day14组合模式.Component;

/**
 * 抽象的父组件对象
 */
public abstract class Component {
    /**
     * 输出组件自身的名称
     */
    public abstract void printStruct(String preStr);

    /**
     * 向组合对象中加入组件对象
     * @param child
     */
    public void addChild(Component child){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }

    /**
     * 从组合对象中移出某个组件对象
     * @param child
     */
    public void removeChild(Component child){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }

    /**
     * 返回某个索引对应的组件对象
     * @param index 需要获取的组件对象的索引,索引从0开始
     * @return 索引对应的组件对象
     */
    public Component getChildren(int index){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }
}

Leaf类

继承一下这个抽象类,别的没有变化

package day14组合模式;

import day14组合模式.Component.Component;

/**
 * 叶子对象
 */
public class Leaf extends Component {
    /**
     * 叶子对象的名字
     */
    private String name = "";

    /**
     * 构造方法,传入叶子对象的名字
     */
    public Leaf(String name){
        this.name = name;
    }

    /**
     * 输出叶子对象的结构
     */
    public void printStruct(String preStr){
        System.out.println(preStr + name);
    }
}

组合对象类

package day14组合模式;

import day14组合模式.Component.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
 * 由于类型不同,需要分开记录
 */
public class Composite extends Component {

    /**
     * 用来存储组合对象中包含的子组件对象
     */
    private List<Component> childComponents = null;

    /**
     * 组合对象的名字
     */
    private String name = "";

    /**
     * 构造方法
     */
    public Composite(String name) {
        this.name = name;
    }


    public void addChild(Component child) {
        // 延迟初始化
        if (childComponents == null) {
            childComponents = new ArrayList<>();
        }
        childComponents.add(child);
    }

    /**
     * 输出组合对象自身的结构
     */
    public void printStruct(String prestr) {
        // 先把自己输出去
        System.out.println(prestr + this.name);
        // 如果还包含有子组件,那么就输出这些子组件对象
        if (this.childComponents != null) {
            prestr += " ";
            // 输出当前对象的子对象了
            for (Component c : childComponents) {
                // 递归输出每个子对象
                c.printStruct(prestr);
            }
        }

    }
}

去掉了之前区分组合对象和叶子对象的方法。

Client

        // 定义所有的组合对象
        Component root = new Composite("服装");
        Component c1 = new Composite("男装");
        Component c2 = new Composite("女装");

        // 定义所有的叶子对象
        Component leaf1 = new Leaf("衬衣");
        Component leaf2 = new Leaf("夹克");
        Component leaf3 = new Leaf("裙子");
        Component leaf4 = new Leaf("套装");

        // 按照树的结构来组合 组合对象和叶子对象
        root.addChild(c1);
        root.addChild(c2);
        c1.addChild(leaf1);
        c1.addChild(leaf2);
        c2.addChild(leaf3);
        c2.addChild(leaf4);

        // 调用跟对象的输出功能来输出整棵树
        root.printStruct("");

组合模式优缺点

 

思考 

本质:统一叶子对象和组合对象,一视同仁全部当成Component对象

何时选用

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/931064.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KVM虚拟化平台安装及创建虚拟机

文章目录 一、KVM 简介二、安装KVM虚拟化平台1、方式一&#xff1a;安装操作系统时&#xff0c;添加虚拟化功能2、方式二&#xff1a;基于现有系统&#xff0c;安装虚拟化功能3、验证KVM安装是否无误 三、创建虚拟机1、创建虚拟机前环境准备工作2、创建CentOS7.5系统虚拟机 一、…

网工必备知识之——防火墙篇

目录 一、背景 二、类型 2.1.过滤防火墙 2.2.应用网关防火墙 2.3.服务防火墙 2.4.监控防火墙 三、功能 3.1.网络安全屏障 3.2.网络安全策略 3.3.进行监控审计 3.4.防止内部信息的外泄 四、五个安全域 五、三种工作模式 5.1交换模式(二层模式): 5.2路由模式(三层…

恶意软件分析和取证:深入研究各类恶意软件,讨论分析技术和数字取证方法,了解攻击者的行为和动机

章节一&#xff1a;引言 在当今数字化的世界中&#xff0c;恶意软件的威胁不断演化&#xff0c;给个人、企业 ja 尤其是政府带来了巨大的安全风险。恶意软件如病毒、木马、蠕虫等形式多样&#xff0c;攻击手段不断升级&#xff0c;导致了信息泄露、财产损失 ja 甚至国家安全的…

【深度学习】实验02 鸢尾花数据集分析

文章目录 鸢尾花数据集分析决策树K-means 鸢尾花数据集分析 决策树 # 导入机器学习相关库 from sklearn import datasets from sklearn import treeimport matplotlib.pyplot as plt import numpy as np# Iris数据集是常用的分类实验数据集&#xff0c; # 由Fisher, 1936收集…

CFC编程入门_【10分钟学会】

什么是CFC&#xff1a; 【差不多10分钟全学会】 CFC是图形化编程&#xff0c; 跟单片机的连线一样&#xff0c; 唯一的区别&#xff1a;功能块右侧是【只能输出】引脚。 只有左侧引脚可以输入输出。 有哪些控件&#xff1a; 指针&#xff1a;用于拖动功能块。 控制点&#xf…

C#将text文本中的单双行分开单独保存

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 文本的分割1.设定text文件的名称为02.文本导出 文本的分割 1.设定text文件的名称为0 代码如下&#xff1a; using System; using System.Collections.Generic; us…

【Seata】01 - Seata XA 模式 Demo 调用流程分析

文章目录 前言参考目录版本说明前置知识1、关于事务的理论知识2、关于 Seata3、Seata 领域模型 测试 Demo1、模块说明2、调用逻辑说明3、分析流程说明4、注意事项 Seata XA 模式 Commit 调用流程分析1、调用流程图2、XA 模式流程以及操作命令3、业务模块&#xff1a;流程入口3.…

掌握Six Sigma:逐步解锁业务流程优化的秘密之匙

一、Six Sigma方法简介 1. Six Sigma的起源和概念 Six Sigma起源于1980年代的摩托罗拉公司。当时的摩托罗拉在面临激烈的全球竞争和持续的质量问题时&#xff0c;发明了这种系统的管理方法&#xff0c;并通过实施&#xff0c;获得了显著的成绩。 所谓的“Six Sigma”&#x…

Tensorflow2.0搭建网络八股

目录 引言&#xff1a;keras与Tensorflow2.0结合 一、六步法 1.导入头文件&#xff1a;import 2.收集处理训练集和测试集&#xff1a;train, test&#xff1a; 3.描述各层网model tf.keras.models.Sequential&#xff1a; 4.描述使用什么优化反向传播&#xff1a;model.c…

Python中使用print()时如何实现不换行

平时刷题的时候大家可能会发现打印字符的时候需要你不换行才能得到正确答案&#xff0c;那么如何实现的。下面直接看例子。 使用print()函数时其实还有个默认的参数end&#xff0c;来看看具体怎么回事 list [a,b,c] for i in list:print(i)打印结果&#xff1a;在这里插入代…

【C/C++】父类指针指向子类对象 | 隐藏

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

CleanMyMac最新版4.14Mac清理软件下载安装使用教程

苹果电脑是很多人喜欢使用的一种电脑&#xff0c;它有着优美的外观&#xff0c;流畅的操作系统&#xff0c;丰富的应用程序和高效的性能。但是&#xff0c;随着时间的推移&#xff0c;苹果电脑也会产生一些不必要的文件和数据&#xff0c;这些文件和数据就是我们常说的垃圾。那…

docker服务如何正确关停

说明&#xff1a;停止 docker 服务之前&#xff0c;先把所有的容器都停掉&#xff0c;如果没停掉&#xff0c;再重启 docker 服务之后&#xff0c;所有的容器就会成为 Exited 状态。如果你只是想停止 docker 服务&#xff0c;docker 中的容器还继续提供服务&#xff0c;需要在d…

NVIDIA DLI 深度学习基础 答案 领取证书

最后一节作业是水果分类的任务&#xff0c;一共6类&#xff0c;使用之前学习的知识在代码段上进行填空。 加载ImageNet预训练的基础模型 from tensorflow import kerasbase_model keras.applications.VGG16(weights"imagenet",input_shape(224, 224, 3),include_t…

首页搜索框传递参数,并在搜索页面中的搜索框中进行显示,搜索框绑定回车键进行搜索

实现搜索条件和搜索内容固定&#xff0c;以及回车键搜索跳转 1.写出搜索条件和搜索框 <form class"parent"><select id"searchSelect" style"border: 1px solid #325da7;border-right: none;" value"resource"><opt…

Mysql B+数索引结构

一、B树和B树区别 二、 B 树形成过程 三、页分裂过程 3.1 页分裂过程实例 3.1.1 原有数据1、3、5形成如下数据页 3.1.2 先新插入数据4&#xff0c;因为 页10 最多只能放3条记录所以我们不得不再分配一个新页&#xff1a; 新分配的数据页编号可能并不是连续的&#xff0c;也…

threejs特殊几何体(一:文字几何体对象)

threejs中文字几何体通过newTextGeometry&#xff08;&#xff09;生成&#xff0c;它被单独作为一个类存在于threejs中const txtGeo new TextGeometry("threejs", { ...opts, font: font }); 我们先看效果&#xff1a; <template><div></div> &…

RJ45接口的PCB设计布局布线注意事项

网口模块的组成主要包括了&#xff1a;RJ45网口、变压器、PHY芯片及主芯片&#xff1b;还有一种RJ45与变压器进行了集成&#xff0c;分别如图1、图2所示&#xff1b; 图1 网口模块组成-RJ45与变压器未集成 图2 网口模块组成-RJ45与变压器集成 我们常见的网口有百兆网口和千兆网…

MySQL学习笔记(八)—— 锁

首先要说明&#xff0c;有的锁是我们自己想加的时候加的&#xff0c;比如全局锁要靠我们自己用命令去加。而有的锁是mysql默认就给你加上了&#xff0c;因为mysql要保证自己最起码的安全性。 InnoDB默认加的是行级锁。 一、全局锁 1.1 用途 全局锁就是把所有的表都给锁了&am…

【UniApp开发小程序】私聊功能后端实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】

声明 本文提炼于个人练手项目&#xff0c;其中的实现逻辑不一定标准&#xff0c;实现思路没有参考权威的文档和教程&#xff0c;仅为个人思考得出&#xff0c;因此可能存在较多本人未考虑到的情况和漏洞&#xff0c;因此仅供参考&#xff0c;如果大家觉得有问题&#xff0c;恳…