Java设计模式-组合模式

简介: Java设计模式-组合模式

微信截图_20220524205013.png


继Java设计模式-外观模式后的组合模式它也来了哦,让我们一起来瞧一瞧吧!!!😁 会了就当复习丫,不会来一起来看看吧。

很喜欢一句话:“八小时内谋生活,八小时外谋发展”。

如果你也喜欢,让我们一起坚持吧!!

共勉😁


初入夏时


设计模式系列


一、前言


1)引入:


在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包、生活用品中的衣服与衣柜、以及厨房中的锅碗瓢盆等。


微信截图_20220524205121.png


在软件开发中也是如此,如,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。


2)概述:


组合模式(Composite Pattern):将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。。


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


3)角色:


1.抽象根节点Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。


2.树枝节点Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。


3.叶子节点Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。


4)使用场景:


1.你想表示对象的部分-整体层次结构


2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。


组合模式正是应树形结构而生,所以组合模式的使用场景就大都是是出现树形结构的地方。


比如:文件目录显示,多级目录呈现等树形结构数据的操作。


二、代码实现


案例:


如下图,我们在访问别的一些管理系统时,经常可以看到类似的菜单。一个菜单可以包含菜单项(菜单项是指不再包含其他内容的菜单条目),也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当,我们的需求是针对一个菜单,打印出其包含的所有菜单以及菜单项的名称。


微信截图_20220524205223.png


要实现该案例,我们先画出类图:


微信截图_20220524205245.png


代码:


不管是菜单还是菜单项,都应该继承自统一的接口,这里姑且将这个统一的接口称为菜单组件。


//菜单组件  不管是菜单还是菜单项,都应该继承该类
public abstract class MenuComponent {
    protected String name;
    protected int level;
    //添加菜单
    public void add(MenuComponent menuComponent){
        System.out.println("文件不能添加菜单");
        throw new UnsupportedOperationException();
    }
    //移除菜单
    public void remove(MenuComponent menuComponent){
        System.out.println("文件不能移除菜单");
        throw new UnsupportedOperationException();
    }
    //获取指定的子菜单
    public MenuComponent getChild(int i){
        System.out.println("文件没有子菜单");
        throw new UnsupportedOperationException();
    }
    //获取菜单名称
    public String getName(){
        return name;
    }
    public void print(){
        throw new UnsupportedOperationException();
    }
}


这里的MenuComponent定义为抽象类,因为有一些共有的属性和行为要在该类中实现,Menu和MenuItem类就可以只覆盖自己感兴趣的方法,而不用搭理不需要或者不感兴趣的方法。


举例来说,Menu类可以包含子菜单,因此需要覆盖add()、remove()、getChild()方法,但是MenuItem就不应该有这些方法。


我这里就是打印句话,然后抛出异常。


Menu


Menu类已经实现了除了getName方法的其他所有方法,因为Menu类具有添加菜单,移除菜单和获取子菜单的功能。


public class Menu extends MenuComponent {
    private List<MenuComponent> menuComponentList;
    public Menu(String name,int level){
        this.level = level;
        this.name = name;
        menuComponentList = new ArrayList<MenuComponent>();
    }
    @Override
    public void add(MenuComponent menuComponent) {
        menuComponentList.add(menuComponent);
    }
    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponentList.remove(menuComponent);
    }
    @Override
    public MenuComponent getChild(int i) {
        return menuComponentList.get(i);
    }
    @Override
    public void print() {
        for (int i = 1; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
        for (MenuComponent menuComponent : menuComponentList) {
            menuComponent.print();
        }
    }
}


MenuItem


MenuItem是菜单项,不能再有子菜单,所以添加菜单,移除菜单和获取子菜单的功能并不能实现。


public class MenuItem extends MenuComponent {
    public MenuItem(String name,int level) {
        this.name = name;
        this.level = level;
    }
    @Override
    public void print() {
        for (int i = 1; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
    }
}


测试


public class Client {
    public static void main(String[] args) {
        MenuComponent component = new Menu("crush",2);
        MenuComponent c2 = new Menu("wyh1",1);
        MenuComponent wyh4 = new MenuItem("wyh4", 2);
        MenuComponent wyh5 = new MenuItem("wyh5", 2);
        component.add(c2);
        component.add(wyh4);
        //wyh4.add(wyh5);
        component.print();  
        /**
         * 输出:
         * --crush
         * wyh1
         * --wyh4
         */
    }
}


上面这个代码案例,是属于组合模式中的透明模式,你没看错,组合模式有两种。我忘记写在前面啦,这里再来给大家介绍一下哈:


  • 透明组合模式


透明组合模式中,抽象根节点角色中声明了所有用于管理成员对象的方法,比如在示例中 MenuComponent 声明了 addremovegetChild 方法,这样做的好处是确保所有的构件类都有相同的接口。透明组合模式也是组合模式的标准形式。


透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的,叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供 add()、remove() 等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用这些方法可能会出错(如果没有提供相应的错误处理代码)


  • 安全组合模式


在安全组合模式中,在抽象构件角色中没有声明任何用于管理成员对象的方法,而是在树枝节点 Menu 类中声明并实现这些方法。安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。


微信截图_20220524205407.png


三、总结


优点


  • 组合模式 屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),将客户代码与复杂的容器对象解耦,使得客户端可以忽略层次间的差异,简化了客户端代码,使用一致的行为控制不同层次。高层模块调用简单。


  • 在 组合模式可以很方便地增加 树枝节点叶子节点 对象,并对现有类库无侵入,符合开闭原则


缺点


  • 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系;


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


  • 不容易用继承的方法来增加构件的新功能;


四、自言自语


你卷我卷,大家卷,什么时候这条路才是个头啊。😇(还是直接上天吧)

有时候也想停下来歇一歇,一直做一个事情,感觉挺难坚持的。😁


你好,如果你正巧看到这篇文章,并且觉得对你有益的话,就给个赞吧,让我感受一下分享的喜悦吧,蟹蟹。🤗


如若有写的有误的地方,也请大家不啬赐教!!


同样如若有存在疑惑的地方,请留言或私信,定会在第一时间回复你。


持续更新中


目录
相关文章
|
9天前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
87 2
|
8天前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
77 0
|
3月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
7天前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
110 35
|
7天前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
85 8
|
6月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
123 0
|
3月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
3月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
6月前
|
设计模式 Java 定位技术
【设计模式】【结构型模式】组合模式(Composite)
一、入门 什么是组合模式 组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次关系。组合模式使得客户端可以统一处理单个对象和组合对
175 10
|
8月前
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
下一篇
开通oss服务