• 设计模式之组合模式


    定义

    将对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。如电脑中文件和文件夹的结构。

    结构

    • Component,抽象构件,为叶子节点对象和组合对象声明公共接口,并实现它们的默认行为。
    • Leaf,叶子节点对象,不包含其他的子节点对象。
    • Composite,组合对象,包含子节点,实现了抽象构件中定义的行为。

    简单实现

    抽象构件

    public abstract class Component {
    
      protected String name;
    
      protected Component(String name) {
        this.name = name;
      }
    
      public void addChild(Component child) {
        throw new UnsupportedOperationException();
      }
    
      public void removeChild(Component child) {
        throw new UnsupportedOperationException();
      }
    
      public Component getChild(int index) {
        throw new UnsupportedOperationException();
      }
    
      public abstract void operation();
    }
    

    叶子节点对象

    public class Leaf extends Component {
    
      public Leaf(String name) {
        super(name);
      }
    
      @Override
      public void operation() {
        System.out.println(name + " operation");
      }
    
    }
    

    组合对象

    import java.util.ArrayList;
    import java.util.List;
    
    public class Composite extends Component {
    
      private final List<Component> children = new ArrayList<>();
    
      public Composite(String name) {
        super(name);
      }
    
      public void addChild(Component child) {
        children.add(child);
      }
    
      public void removeChild(Component child) {
        children.remove(child);
      }
    
      public Component getChild(int index) {
        if (index < 0 || index >= children.size()) {
          return null;
        }
        return children.get(index);
      }
    
      @Override
      public void operation() {
        System.out.println(name + " operation");
        for (Component child : children) {
          child.operation();
        }
      }
    }
    

    客户端

    public class Client {
    
      public static void main(String[] args) {
        //定义多个构件并组合成树形结构
        Component root = new Composite("C盘");
        Component dir1 = new Composite("目录1");
        Component dir2 = new Composite("目录2");
        Component dir11 = new Composite("目录11");
        Component file1 = new Leaf("文件1");
        Component file2 = new Leaf("文件2");
        dir1.addChild(dir11);
        dir11.addChild(file1);
        dir2.addChild(file2);
        root.addChild(dir1);
        root.addChild(dir2);
        root.operation();
        System.out.println("==========");
        root.removeChild(dir1);
        root.operation();
        System.out.println("==========");
        root.getChild(0).operation();
      }
    
    }
    

    组成的树形结构为

    安全式和透明式

    组合模式分为透明式的组合模式和安全式的组合模式。

    • 透明式,抽象构件声明了子类中的所有方法,所以客户端不需要区分叶子对象和组合对象,对客户端来说是透明的,
      但叶子对象本来没有addChild(),removeChild()方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
    • 将管理子节点的方法转移到组合对象中,抽象构件和叶子节点中没有管理子节点的方法,这样就避免了上一种方式的安全性问题,
      但由于叶子节点对象和组合对象有不同的接口,客户端需要区分这两种对象,所以失去了透明性。

    上面的示例实现就是透明式,下面实现一下安全式。

    public abstract class Component {
    
      protected String name;
    
      protected Component(String name) {
        this.name = name;
      }
    
      public abstract void operation();
    }
    

    客户端

    public class Client {
    
      public static void main(String[] args) {
        //定义多个构件并组合成树形结构
        Composite root = new Composite("C盘");
        Composite dir1 = new Composite("目录1");
        Composite dir2 = new Composite("目录2");
        Composite dir11 = new Composite("目录11");
        Component file1 = new Leaf("文件1");
        Component file2 = new Leaf("文件2");
        dir1.addChild(dir11);
        dir11.addChild(file1);
        dir2.addChild(file2);
        root.addChild(dir1);
        root.addChild(dir2);
        root.operation();
        System.out.println("==========");
        root.removeChild(dir1);
        root.operation();
        System.out.println("==========");
        root.getChild(0).operation();
      }
    
    }
    

    叶子节点对象和组合对象都没有改变。

    组合模式在Spring的实现

    Spring中的CompositeIterator和CompositeCacheManager

    Spring中很多地方都使用到了组合模式(安全式)。

    总结

    优点

    1. 简化了客户端调用,客户端不需要区分叶子对象和组合对象。
    2. 可以很方便的增加新的叶子对象或组合对象,符合开闭原则。
    3. 可以组成一个复杂的树形结构,并且很容易控制。

    缺点

    1. 很难限制组合对象中的组件类型,例如限制某个文件夹对象中只能包含文本文件,这种情况就很难实现。

    本质

    组合模式的本质是统一叶子对象和组合对象。正因为统一了这两种类型的对象,才能组成复杂的树形结构。

    使用场景

    1. 在具有整体和部分的层次结构中,希望统一这两种结构的操作。

    参考

    大战设计模式【13】—— 组合模式
    设计模式的征途—9.组合(Composite)模式
    设计模式(十)——组合模式(HashMap源码解析)
    组合模式(详解版)
    《JAVA设计模式》之组合模式(Composite)
    研磨设计模式-书籍

  • 相关阅读:
    通过登入IP记录Linux所有用户登录所操作的日志
    PHP写的异步高并发服务器,基于libevent
    PHP event 事件机制
    PHP高级工程师的要求
    TBS 手册 --phpv 翻译
    两局域网互联解决方案
    比ngx_http_substitutions_filter_module 更强大的替换模块sregex的replace-filter-nginx-module
    直播平台虚拟币与人民币的关系
    查询出来的东西异步缓存
    如何解决GBK的编码的文件中的中文转换成为UTF-8编码的文件而且不乱码
  • 原文地址:https://www.cnblogs.com/strongmore/p/15191426.html
Copyright © 2020-2023  润新知