Android开发Android开发经验谈Android技术知识

组合模式

2020-05-14  本文已影响0人  不正经的创作者

介绍

组合模式(Composite Pattern)也称为部分整体模式 (Part Whole Pattern) ,属于结构性设计模式,组合模式比较简单,它将一组相似的对象看做一个对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问相应的对象,以此忽略掉对象与对象集合之间的差别。

定义

将对象组合成树形结构以表示 ”部分-整体“ 的层次结构,使得用户对整个对象和组合对象的使用具有一致性。

使用场景

UML 类图

代码示例

简单示例

抽象根节点:

  public abstract class Component {

      /**
       * 节点名称
       */
      protected String name;

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

      /**
       * 具体的逻辑方法由子类实现
       */
      public abstract void doSomething();

      /**
       * 添加子节点
       * @param component
       */
      public abstract void addChild(Component component);

      /**
       * 移除子节点
       * @param component
       */
       public abstract void removeChild(Component component);

      /**
       * 获取子节点
       * @param index
       * @return
       */
      public abstract Component getChildren(int index);

  }

枝干节点:

  public class Composite extends Component {
      /**
       * 存储节点的容器
       */
      private List<Component> mLists = new ArrayList<>();

      public Composite(String name) {
          super(name);
      }

      @Override
      public void doSomething() {
          System.out.println("name: " + name);
          if (mLists != null && mLists.size() > 0) {
              for (Component component : mLists) {
                  component.doSomething();
              }
          }
      }

      @Override
      public void addChild(Component component) {
          mLists.add(component);
      }

      @Override
      public void removeChild(Component component) {
          mLists.remove(component);
      }

      @Override
      public Component getChildren(int index) {
          return mLists.get(index);
      }
  }

叶子节点:

  public class Leaf extends Component {
      public Leaf(String name) {
          super(name);
      }

      @Override
      public void doSomething() {
          System.out.println("name: " + name);

      }

      @Override
      public void addChild(Component component) {
          throw new UnsupportedOperationException("叶子节点没有子节点");
      }

      @Override
      public void removeChild(Component component) {
          throw new UnsupportedOperationException("叶子节点没有子节点");
      }

      @Override
      public Component getChildren(int index) {
          throw new UnsupportedOperationException("叶子节点没有子节点");
      }
  }

test:

      @Test
      public void testComponent() {
        //构造一个根节点
        Component root = new Composite("Root");

        //构造枝干节点
        Component branchA = new Composite("branchA");
        Component branchB = new Composite("branchB");

        //构造叶子节点
        Component leafA = new Leaf("leafA");
        Component leafB = new Leaf("LeafB");

        //将叶子节点添加至枝干节点中
        branchA.addChild(leafA);
        branchB.addChild(leafB);

        //将枝干节点添加进跟节点
        root.addChild(branchA);
        root.addChild(branchB);

        root.doSomething();
    }

output:

  name: Root
  name: branchA
  name: leafA
  name: branchB
  name: LeafB

实战

业务背景: 用代码表示文件夹跟文件的组合关系;

文件和文件夹抽象类:

  public abstract class Dir {
      /**
       * 声明一个 List 成员变量存储文件夹下面所有元素
       */
      protected List<Dir> mDirs = new ArrayList<>();

      /**
       * 当前文件或文件夹名称
       */
      protected String name;
  
      public Dir(String name) {
          this.name = name;
      }

      /**
       * 添加一个文件或文件夹
       * @param dir
       */
      public abstract void addDir(Dir dir);

      /**
       * 移除一个文件或文件夹
       * @param dir
       */
      public abstract void removeDir(Dir dir);
  
      /**
       * 清空文件夹下面所有的元素
       */
      public abstract void clear();

      /**
       * 输出文件夹下目录结构
       */
      public abstract void print();

      /**
       * 获取文件夹下所有的文件或子文件夹
       */
      public abstract List<Dir> getFiles();

      /**
       * 获取文件或文件夹名称
       * @return
       */
      public String getName(){
          return name;
      }
  }

具体文件夹类:

  public class Folder extends Dir {
      public Folder(String name) {
          super(name);
      }

      @Override
      public void addDir(Dir dir) {
          mDirs.add(dir);

      }

      @Override
      public void removeDir(Dir dir) {
          mDirs.remove(dir);
      }

      @Override
      public void clear() {
          mDirs.clear();
      }

      @Override
      public void print() {
          System.out.print(getName() + " (");
          Iterator<Dir> iterator = mDirs.iterator();
          while (iterator.hasNext()) {
              Dir dir = iterator.next();
              dir.print();
              if (iterator.hasNext()) {
                  System.out.print(", ");
              }
          }
          System.out.print(")");
       }
    @Override
      public List<Dir> getFiles() {
          return mDirs;
      }
  }

具体文件类:

  public class File extends Dir {
      public File(String name) {
          super(name);
      }

      @Override
      public void addDir(Dir dir) {
          throw new UnsupportedOperationException("文件对象不支持该操作");
      }

      @Override
      public void removeDir(Dir dir) {
          throw new UnsupportedOperationException("文件对象不支持该操作");
      }

      @Override
      public void clear() {
          throw new UnsupportedOperationException("文件对象不支持该操作");
      }

      @Override
      public void print() {
          System.out.println("name: "+name);
      }

      @Override
      public List<Dir> getFiles() {
          throw new UnsupportedOperationException("文件对象不支持该操作");
      }
  }

test:

    @Test
    public void testComponent2(){
        //构造一个目录对象表示 sdcard 盘跟目录
        Dir diskSdcard = new Folder("sdcard");

        // sdcard 下有一个文件
        diskSdcard.addDir(new File("bug.log"));

        //sdcard 下还有一个子目录  android
        Dir android =  new Folder("android");
        //android 目录下有一个目录
        Dir data = new Folder("data");
        data.addDir(new File("2019-09-14.log"));
        android.addDir(data);
        diskSdcard.addDir(android);

        //sdcard 下还有一个子目录 baidu
        Dir baidu =  new Folder("baidu");
        //android 目录下有一个目录
        Dir cache = new Folder("cache");
        cache.addDir(new File("offline.baidu"));
        baidu.addDir(cache);
        diskSdcard.addDir(baidu);

        //sdcard 下还有一个子目录 downloads
        Dir downloads =  new Folder("downloads");
        //android 目录下有一个目录
        Dir f360 = new Folder("360");
        f360.addDir(new File("360.log"));
        downloads.addDir(f360);
        diskSdcard.addDir(downloads);

        //打印文件结构
        diskSdcard.print();
    }

output:

  sdcard (
    //文件
    name: bug.log, 
    //文件夹
    android (data (name: 2019-09-14.log)),
    baidu (cache (name: offline.baidu)), 
    downloads (360 (name: 360.log))
  )

这里我们以括号作为一个文件夹的内容范围,如上输出所以 adcard 下文件夹有 3 个子文件夹 Android、baidu、downloads 子文件夹,以及一个 bug.log 文件,而在 3 个子文件夹中还各自包含子文件夹和文件,一个典型的树状嵌套解耦,这就是一个组合模式。

总结

优点:

缺点:

上一篇 下一篇

猜你喜欢

热点阅读