从零开始学设计模式(十一):组合模式(Composite Pattern):

简介: 组合模式(Composite Pattern)又叫做部分-整体模式,它在树型结构(可以想象一下数据结构中的树)的问题中,模糊了简单元素和复杂元素的概念,客户端程序可以像处理简单元素一样来处理复杂元素,而使得客户端程序与复杂元素的内部结构进行解藕。

定义:


组合模式(Composite Pattern)又叫做部分-整体模式,它在树型结构(可以想象一下数据结构中的树)的问题中,模糊了简单元素和复杂元素的概念,客户端程序可以像处理简单元素一样来处理复杂元素,而使得客户端程序与复杂元素的内部结构进行解藕。


组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。


如下图的工程目录结构就是一个树型结构:


d113abd5b9ca4529b459117631381872~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


它可以表示为下面的树型结构图:


e936205fd1624040b61b534f166ac365~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


由上面的结构图可以发现,根节点和树枝节点其实在本质上属于同一种数据类型,它们都可以作为容器使用;但是叶子节点与树枝节点其实在语义上是不属于同一种类型。但是在组合模式中,是把树枝节点和叶子节点看作属于同一种数据类型(这里是用统一接口定义),从而使得让它们具备一致行为。


所以在组合模式中,整个的树形结构中的对象就会都属于同一种类型,这样的好处就是不需要用户来辨别是树枝节点还是叶子节点,就可以直接进行操作,给用户的使用带来极大的便利。


组成部分:


通过上述对于组合模式的描述,可以总结出组合模式的几个组成部分:


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


2、Leaf: 在组合中表示叶子结点对象,叶子结点没有子结点。


3、Composite: 容器对象,表示参加组合的有子对象的对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加和删除等。


栗子


用上面文件夹的例子,首先声明一个文件夹相关的Component,FolderComponent:


public abstract class FolderComponent {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(final String name) {
        this.name = name;
    }
    public FolderComponent() {
    }
    public FolderComponent(final String name) {
        this.name = name;
    }
    public abstract void add(FolderComponent component);
    public abstract void remove(FolderComponent component);
    public abstract void display();
}
复制代码


再声明一个叶子节点文件夹,定义为FileLeaf,并且继承上面的FolderComponent:


public class FileLeaf  extends FolderComponent{
    public FileLeaf(final String name) {
        super(name);
    }
    @Override
    public void add(FolderComponent component) {
    }
    @Override
    public void remove(FolderComponent component) {
    }
    @Override
    public void display() {
        System.out.println("叶子文件:" + this.getName());
    }
}
复制代码


最后声明一个容器对象,FolderComposit


public class FolderComposite extends FolderComponent {
    private final List<FolderComponent> components;
    public FolderComposite(final String name) {
        super(name);
        this.components = new ArrayList<FolderComponent>();
    }
    public FolderComposite() {
        this.components = new ArrayList<FolderComponent>();
    }
    @Override
    public void add(final FolderComponent component) {
        this.components.add(component);
    }
    @Override
    public void remove(final FolderComponent component) {
        this.components.remove(component);
    }
    @Override
    public void display() {
        System.out.println("文件夹组合容器的名字是" + this.getName());
        for (final FolderComponent component : components) {
            System.out.println("文件夹组合容器的当前文件夹是" + component.getName());
        }
    }
}
复制代码


测试方法:


public class CompositePatternTest {
    public static void main(final String[] args)    {
        final FolderComponent leaf = new FileLeaf("叶子文件");
        leaf.display();
        final FolderComponent folder = new FolderComposite("文件夹一");
        folder.add(new FileLeaf("文件夹里面的文件二"));
        folder.add(new FileLeaf("文件夹里面的文件三"));
        folder.display();
    }
}
复制代码


运行结果如下:


f4b4accf53a9434596b0571bc71df0f0~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


通过上面的例子可以总结出组合模式的优点和缺点。


组合模式的优点


1、组合模式使得客户端代码可以一致地处理单个对象和组合对象,从而无须关心自己处理的是单个对象,还是组合对象,大大地简化了代码结构;


2、组合模式的使用使得更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,实现了设计模式原则的“开闭原则”;


组合模式的缺点


1、使用组合模式需要花较多地时间理清类之间的层次关系,所以设计较复杂;


2、组合模式理解和设计较为复杂,增加代码难度;


3、如果使用了组合模式就不容易限制容器中的构件;


4、组合模式中不容易用继承的方法来增加构件的新功能;


使用场景


组合模式适用于以下情况:


1、当想要表示对象的部分-整体层次结构


2、当想要用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。


总结


使用组合模式方便解耦客户端与复杂元素的内部结构,从而使得客户端程序可以像处理简单元素一样来一致处理复杂元素,大大简化了代码。对于层次结构的系统对象,可以使用组合模式进行处理。

目录
相关文章
|
5月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 组合模式
js设计模式【详解】—— 组合模式
64 7
|
3月前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
3月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
3月前
|
设计模式 存储 安全
Java设计模式-组合模式(13)
Java设计模式-组合模式(13)
|
3月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
5月前
|
设计模式
对抗软件复杂度问题之组合(Composite)方法设计模式是什么,如何解决
对抗软件复杂度问题之组合(Composite)方法设计模式是什么,如何解决
|
6月前
|
设计模式
设计模式-05建造者模式(Builder Pattern)
设计模式-05建造者模式(Builder Pattern)
|
6月前
|
设计模式 存储 安全
Java设计模式:组合模式之透明与安全的两种实现(七)
Java设计模式:组合模式之透明与安全的两种实现(七)
|
6月前
|
设计模式 Java
Java设计模式之组合模式详解
Java设计模式之组合模式详解
|
7月前
|
设计模式 安全 Java
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)
该文介绍了一种C++的编程技巧——奇异递归模板模式(CRTP),旨在让派生组件能继承基本组件的特定功能。通过示例展示了如何创建一个`Fighter`接口和`MmaFighter`类,其中`MmaFighter`及其子类如`MmaBantamweightFighter`和`MmaHeavyweightFighter`强制类型安全,确保相同重量级的拳手之间才能进行比赛。这种设计避免了不同重量级拳手间的错误匹配,编译时会报错。CRTP适用于处理类型冲突、参数化类方法和限制方法只对相同类型实例生效的情况。