java设计模式:03-03-组合模式

组合模式(Composite Pattern)

组合模式(Composite Pattern)是一种结构型设计模式,它将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式的应用场景

  • 需要表示对象的部分-整体层次结构:如文件系统中的目录和文件,图形系统中的图形和组合图形。
  • 希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象:如菜单和菜单项的处理。
  • 需要对树形结构中的节点和叶子节点进行相同的操作:如组织结构图中的部门和员工。

组合模式的实现方式

1. 透明组合模式

思想:通过定义一个抽象的组件类,所有的叶子节点和组合节点都继承自该组件类,使得客户端可以一致地处理叶子节点和组合节点。

实现方式

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 抽象组件类
abstract class Component {
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    public Component getChild(int i) {
        throw new UnsupportedOperationException();
    }

    public abstract void operation();
}

// 叶子节点
class Leaf extends Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    public void operation() {
        System.out.println("Leaf " + name + " is visited");
    }
}

// 组合节点
class Composite extends Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public Component getChild(int i) {
        return children.get(i);
    }

    public void operation() {
        for (Component child : children) {
            child.operation();
        }
    }
}

// 客户端代码
public class CompositePattern {
    public static void main(String[] args) {
        Component root = new Composite();
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");

        root.add(leaf1);
        root.add(leaf2);

        Component subComposite = new Composite();
        Component leaf3 = new Leaf("3");
        subComposite.add(leaf3);

        root.add(subComposite);
        root.operation();
    }
}

优点

  • 定义了包含基本对象和组合对象的类层次结构,使得客户端可以一致地使用这些对象。
  • 组合结构可以任意扩展,符合开闭原则。
  • 简化客户端代码,使得客户端可以一致地处理叶子节点和组合节点。

缺点

  • 使得叶子节点和组合节点的接口变得复杂,因为对于叶子节点来说,某些方法是没有意义的(如addremove方法)。
2. 安全组合模式

思想 :通过将子节点操作(如addremove方法)放在组合节点中,而不是抽象组件类中,使得叶子节点的接口更加简洁。

实现方式

java 复制代码
import java.util.ArrayList;
import java.util.List;

// 抽象组件类
abstract class Component {
    public abstract void operation();
}

// 叶子节点
class Leaf extends Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    public void operation() {
        System.out.println("Leaf " + name + " is visited");
    }
}

// 组合节点
class Composite extends Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public Component getChild(int i) {
        return children.get(i);
    }

    public void operation() {
        for (Component child : children) {
            child.operation();
        }
    }
}

// 客户端代码
public class SafeCompositePattern {
    public static void main(String[] args) {
        Composite root = new Composite();
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");

        root.add(leaf1);
        root.add(leaf2);

        Composite subComposite = new Composite();
        Component leaf3 = new Leaf("3");
        subComposite.add(leaf3);

        root.add(subComposite);
        root.operation();
    }
}

优点

  • 使得叶子节点的接口更加简洁,不需要实现组合节点特有的方法。
  • 客户端只能通过组合节点来操作子节点,避免了叶子节点和组合节点的混淆。

缺点

  • 需要在客户端中区分叶子节点和组合节点,增加了客户端代码的复杂性。
  • 不能保证客户端一致地处理叶子节点和组合节点,可能会导致操作上的不一致。

总结

实现方式 优点 缺点
透明组合模式 客户端可以一致地处理叶子节点和组合节点,简化客户端代码 使叶子节点的接口变得复杂,增加了不必要的方法
安全组合模式 叶子节点接口简洁,不需要实现组合节点特有的方法 需要在客户端中区分叶子节点和组合节点,增加了代码复杂性

选择哪种实现方式应根据具体的需求和系统的复杂度来决定。如果系统中需要一致地处理叶子节点和组合节点,透明组合模式较为合适。如果希望叶子节点的接口简洁,可以选择安全组合模式。

相关推荐
INFINI Labs10 小时前
使用 Docker Compose 轻松实现 INFINI Console 离线部署与持久化管理
java·docker·eureka·devops·docker compose·console·easyserach
Cosolar10 小时前
国产麒麟系统 aarch64 架构 PostgreSQL 15 源码编译安装完整教程
java·后端
GalaxyPokemon10 小时前
PlayerFeedback 插件开发日志
java·服务器·前端
天天摸鱼的java工程师11 小时前
别再写那些重复代码了!8年Java老兵教你用 Hutool 提升开发效率
java·后端
喝杯绿茶11 小时前
springboot中的事务
java·spring boot·后端
昨天的猫11 小时前
原来项目中的观察者模式是这样玩的
后端·设计模式
麦兜*11 小时前
多阶段构建:打造最小化的 Spring Boot Docker 镜像
java·spring boot·后端·spring cloud·docker
oak隔壁找我11 小时前
Spring Boot Starter 入门教程
java·后端
YoungP11 小时前
【Effective Java 条目一】-- 用静态工厂方法替代构造器
java
高山上有一只小老虎11 小时前
求最大连续bit数
java·算法