谈谈对组合模式的看法

简介: 谈谈对组合模式的看法

组合模式

概叙

在计算机文件系统中,文件夹既可以放文件,也可以放文件夹(子文件夹)。在子文件夹中,一样既可以放文件,也可以放子文件夹。可以说,文件夹形成了一种容器结构、递归结构

虽然文件和文件夹是不同类型,但是都可以被放入文件夹中,。文件和文件夹有时也被统称为“目录条目”。在目录条目中,文件夹和文件被当作同一种对象看待(即一致性)。

将文件夹和文件都当作目录条目看待,将容器和内容作为同一种东西看待,可以帮助我们方便的处理问题。在容器中既可以放入内容,也可以放入小容器,在小容器中,又可以放入更小的容器。。。。。这样,就形成了容器结构、递归结构。

Composite模式就是用于创造这种结构的模式。能够时容器与内容具有一致性,创造递归结构。

示例程序

类的一览表

Entity抽象类,用来实现File和Directory的一致性File表示文件的类Directory表示文件夹的类Main测试入口

类图

image.png

代码

Entry类

抽象父类,File和Directory是其子类。

通过getName()获取名字,getSize()获取大小。

add()方法是向文件夹中放入文件(此处抛出异常,Directory需要将其覆盖)。

printList()为外部调用,printList(String prefix)为子类调用。

public abstract class Entity {
   public abstract String getName();    //获取名字
   public abstract int getSize();      //获取大小
   public Entity add(Entity entity) throws Exception {
     throw new RuntimeException("运行异常");       //加入目录条目
   }
   public void printList() {
     printList("");        //显示目录条目一览
   }
   protected abstract void printList(String prefix);  //为一览加上前缀
   @Override
   public String toString() {        //显示代表类文字
     return getName() + "(" + getSize() + ")";
   }
}

File类

name表示文件名,size表示文件大小。

实现printList(String prefix) 方法。

public class File extends Entity {
   private String name;
   private int size;
  public File(String name, int size) {
     this.name = name;
     this.size = size;
   }
   @Override
   public String getName() {
     return name;
   }
   @Override
   public int getSize() {
     return size;
   }
   @Override
   protected void printList(String prefix) {
     System.out.println(prefix + "/" + this);
   }
}

Directory类

表示文件夹的类,是Entity的子类。

name表示文件夹名,directory保存文件夹的目录条目(指定泛型Entity)。

getSize(),通过计算得出大小。size += entity.getSize()。entity不论是File的实例还是Directory的实例,我们都可以通过getSize得到它的大小。 这就是Composite模式的特征——“容器与内容的一致性”。

如果entity是Directory的实例,调用getSize()会将该文件夹下的所有目录条目大小加起来。如果还有子文件夹,又会调用getSize()方法,形成递归调用。getSize()方法的递归调用与Composite模式的结构是相对应的。

add方法用于向文件夹中加入子文件夹或文件。

public class Directory extends Entity {
   private String name;
   private ArrayList<Entity> directory = new ArrayList();
   public Directory(String name) {
     this.name = name;
   }
   @Override
   public String getName() {
     return name;
   }
   @Override
   public int getSize() {
     int size = 0;
     Iterator<Entity> it = directory.iterator();
     while (it.hasNext()) {
       Entity entity = it.next();
       size += entity.getSize();
     }
     return size;
   }
   @Override
   public Entity add(Entity entity) throws Exception {
     directory.add(entity);
     return this;
   }
   @Override
   protected void printList(String prefix) {
     System.out.println(prefix + "/" + this);
     Iterator<Entity> it = directory.iterator();
     while (it.hasNext()) {
       Entity entity = it.next();
       entity.printList(prefix + "/" + name);
     }
   }
}

Main类

public class Main {
   public static void main(String[] args) {
     try {
       System.out.println("making root entries......");
       Directory rootDir = new Directory("root");
       Directory binDir = new Directory("bin");
       Directory tmpDir = new Directory("tmp");
       Directory usrDir = new Directory("usr");
       rootDir.add(binDir);
       rootDir.add(tmpDir);
       rootDir.add(usrDir);
       binDir.add(new File("vi", 10000));
       binDir.add(new File("latex", 20000));
       rootDir.printList();
       System.out.println("");
       System.out.println("making usr entries......");
       Directory yuki = new Directory("yuki");
       Directory hanako = new Directory("hanako");
       Directory tomura = new Directory("tomura");
       usrDir.add(yuki);
       usrDir.add(hanako);
       usrDir.add(tomura);
       yuki.add(new File("diary.html", 100));
       hanako.add(new File("memo.txt", 200));
       tomura.add(new File("game.doc", 300));
       tomura.add(new File("junk.mail", 500));
       rootDir.printList();
     } catch (Exception e) {
       e.printStackTrace();
     }
   }
}
making root entries......
/root(30000)
/root/bin(30000)
/root/bin/vi(10000)
/root/bin/latex(20000)
/root/tmp(0)
/root/usr(0)
making usr entries......
/root(31100)
/root/bin(30000)
/root/bin/vi(10000)
/root/bin/latex(20000)
/root/tmp(0)
/root/usr(1100)
/root/usr/yuki(100)
/root/usr/yuki/diary.html(100)
/root/usr/hanako(200)
/root/usr/hanako/memo.txt(200)
/root/usr/tomura(800)
/root/usr/tomura/game.doc(300)
/root/usr/tomura/junk.mail(500)

登场角色

  1. Leaf(树叶)
  2. 表示内容角色,不能放入其他物品。(File)
  3. Composite(复合物)
  4. 表示容器角色,可以放入容器和树叶。(Directory)
  5. Component
  6. 使leaf与Composite具有一致性,是其父类(Entity)
  7. client
  8. 使用角色,(Main)

拓展

多个和单个的一致性

Composite模式可以使容器与内容具有一致性,也可称其为,多个和单个一致性,即将多个对象结合在一起,当作一个对象下使用。

add方法

  1. 定义在Entity中,默认报错
  2. 能够使用add方法的只有Directory
  3. 定义在Entity中,什么也不做
  4. 声明但不实现
  5. 声明抽象方法,子类实现。(这样的话File类中也必须定义完全没有用add方法)
  6. 定义在Directory中


目录
相关文章
|
设计模式 关系型数据库
设计模式八大原则知多少
设计模式是一种通用的解决问题的经验,可以帮助我们设计出可重用、可维护和可扩展的软件。
|
6月前
|
设计模式 缓存 算法
谈谈我工作中的23个设计模式
从基础的角度看,设计模式是研究类本身或者类与类之间的协作模式,是进行抽象归纳的一个很好的速成思路。后面阅读设计模式后,为了加深理解,对相关图片进行了描绘和微调。 从技术的角度已经有很多好的总结,本文会换一种角度思考,既然设计模式研究的是类与类的关系,我们作为工作的个体,一些工作中的策略是不是也可以进行类比,可以更好地去思考这些模式?答案是肯定的。
|
6月前
|
设计模式 存储 缓存
设计模式全览:编程艺术的精髓!
设计模式全览:编程艺术的精髓!
44 0
|
6月前
|
设计模式 缓存 算法
C/C++设计模式之道:选择与权衡
C/C++设计模式之道:选择与权衡
142 1
|
设计模式 SQL Java
设计模式的七大原则(设计模式必修课)
设计模式(Design Pattern)是针对于软件设计中反复出现的问题所提出来的一个解决方案,是前人对代码开发经验的总结,它不是语法规定,学好设计模式可以开阔我们的编程思维,让我们编写的程序具备可复用性、可扩展性、可读性、可靠性以及安全性等;
7809 0
|
6月前
|
设计模式 SQL 缓存
设计模式概括认知
设计模式概括认知
41 0
|
设计模式 架构师 Java
白活了!谷歌架构师10年心血汇成的《24种设计模式》,这才是正解
设计模式 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。一看代码一团糟,那这人肯定不怎么样。 现在各种开源框架里满满都是设计模式,所以可以不用但是最好要懂,除非一辈子CRUD,不看框架。
|
设计模式 Java 程序员
设计模式 - 基本功的重要性
设计模式 - 基本功的重要性
97 0
|
设计模式 Java 关系型数据库
我终于读懂了设计模式的七大原则。。。
我终于读懂了设计模式的七大原则。。。
我终于读懂了设计模式的七大原则。。。
|
设计模式 数据库 容器
领略设计模式的魅力,谈谈组合模式搭配访问者模式
组合模式(composite) 我们都知道文件和文件夹的概念,并且文件是可以存放在文件夹中,文件夹中也可以存放其他文件夹。需要设计一个简单的程序来实现文件夹和文件的关系。 实现思路 文件夹需要存放文件夹和文件,首先想到的是在文件夹中设计两个集合分别来存放文件夹和文件。 有展示文件路径需求时,不清楚在最里层是文件夹还是文件,所以需要把文件夹和文件当做一个对象来处理会更好,都是条目。所以需要创建一个他们共同的父类。 对文件夹的设计优化,创建一个集合容器,容器类型是父类,即解决了既要存放文件夹又要存放文件的问题。