Java实现组合模式:一步步指南
发表时间: 2024-05-17 11:17
组合模式最初只是用于解决树形结构的场景,更多的是处理对象组织结构之间的问题。而组合关系则是通过将不同对象封装起来完成一个统一功能
组合模式(composite pattern)的定义是:将对象组合成树形结构以表示整个部分的层次结构。组合模式可以让用户统一对待单个对象和对象的组合
列出某一目录下所有的文件和文件夹
/** * @Description: 抽象类(文件夹+文件) * @author: zhuoyue * @since: 2024/05/13 15:32 */public abstract class Entry { public abstract String getName(); public abstract int getSize(); /** * 添加文件或文件夹 * @param entry * @return */ public abstract Entry add(Entry entry); /** * 显示指定目录下的所有文件的信息 * @param entry */ public abstract void printList(String entry); @Override public String toString() { return getName()+"("+getSize()+")"; }}public class File extends Entry{ 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 public Entry add(Entry entry) { return null; } @Override public void printList(String entry) { System.out.println(entry+"/"+this); } public void setSize(int size) { this.size = size; }}public class Directory extends Entry{ private String name; private ArrayList<Entry> directory = new ArrayList<>(); public Directory(String name) { this.name = name; } @Override public String getName() { return null; } @Override public int getSize() { int size = 0; for (Entry entry: directory){ size += entry.getSize(); } return size; } @Override public Entry add(Entry entry) { directory.add(entry); return this; } @Override public void printList(String prefix) { System.out.println(prefix+"/"+this); for (Entry entry: directory){ entry.printList(prefix+"/"+name); } }}public class Client { public static void main(String[] args) { /** * 根节点 */ Directory rootDir = new Directory("root"); /** * 树枝节点 */ Directory binDir = new Directory("bin"); binDir.add(new File("vi",10000)); binDir.add(new File("test",20000)); Directory tmpDir = new Directory("tmp"); Directory usrDir = new Directory("usr"); Directory mysqlDir = new Directory("mysql"); mysqlDir.add(new File("my.cnf",30)); mysqlDir.add(new File("test.db",25000)); usrDir.add(mysqlDir); rootDir.add(mysqlDir); rootDir.add(binDir); rootDir.add(tmpDir); rootDir.add(usrDir); rootDir.printList(""); }}
在透明组合模式中,抽象根节点橘色中声明了所有用于管理成员对象的方法。
缺点是不够安全,因为叶子对象和容器对象本质上还是有区别的,叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供add()、remove()等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用者这些方法可能会出错,(可以抛出异常)
2. 安全组合模式
在抽象构件角色中不声明任何用于管理成员对象的方法,而是在树枝节点类中声明并实现这些方法。安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件中定义,因此客户端不能完全针对抽象编程,必须有区别的针对叶子构件和容器构件