• 《图解设计模式》读书笔记5-1 composite模式



    Composite模式即组合模式。它能够使容器和内容具有一致性,创造出递归结构

    举个例子:在文件系统中,文件夹既是内容,也是容器,具有一致性,这样一来,文件系统形成递归结构。组合模式就是用来创建这种结构的。

    代码

    下面这段代码以文件系统为例实现了组合模式。

    UML

    Entry类

    表示目录条目,将文件和文件夹的共有属性抽取出来。

    public abstract class Entry {
        public abstract String getName();                               
        public abstract int getSize();                                 
    
        public Entry add(Entry entry) throws RuntimeException {   
            throw new RuntimeException();
        }
    
        public void printList() {                                      
            printList("");
        }
    
        protected abstract void printList(String prefix);              
    
        public String toString() {                                      
            return getName() + " (size : " + getSize() + ")";
        }
    }
    
    
    

    File类

    表示文件

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

    Directory类

    表示文件夹

    public class Directory extends Entry {
        private String name;                    
        private ArrayList directory = new ArrayList();     
        public Directory(String name) {  
            this.name = name;
        }
        public String getName() {
            return name;
        }
        //获取文件夹的总大小,递归操作
        public int getSize() {
            int size = 0;
            Iterator it = directory.iterator();
            while (it.hasNext()) {
                Entry entry = (Entry)it.next();
                size += entry.getSize();
            }
            return size;
        }
        public Entry add(Entry entry) {
            directory.add(entry);
            return this;
        }
        protected void printList(String prefix) {
            System.out.println(prefix + "/" + this);
            Iterator it = directory.iterator();
            while (it.hasNext()) {
                Entry entry = (Entry)it.next();
                entry.printList(prefix + "/" + name);
            }
        }
    }
    

    Main类

    public class Main {
        public static void main(String[] args) {
            try {
                System.out.println("创建根目录");
                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("创建用户目录");
                Directory xiaoming = new Directory("小明");
                Directory xiaohong = new Directory("小红");
                Directory xiaohua = new Directory("小花");
                usrdir.add(xiaoming);
                usrdir.add(xiaohong);
                usrdir.add(xiaohua);
                xiaoming.add(new File("diary.html", 100));
                xiaoming.add(new File("Composite.java", 200));
                xiaohua.add(new File("memo.tex", 300));
                xiaohong.add(new File("game.doc", 400));
                xiaohong.add(new File("junk.mail", 500));
                rootdir.printList();
            } catch (FileTreatmentException e) {
                e.printStackTrace();
            }
        }
    }
    
    结果
    /*
    创建根目录
    /root (size : 30000)
    /root/bin (size : 30000)
    /root/bin/vi (size : 10000)
    /root/bin/latex (size : 20000)
    /root/tmp (size : 0)
    /root/usr (size : 0)
    
    创建用户目录
    /root (size : 31500)
    /root/bin (size : 30000)
    /root/bin/vi (size : 10000)
    /root/bin/latex (size : 20000)
    /root/tmp (size : 0)
    /root/usr (size : 1500)
    /root/usr/小明 (size : 300)
    /root/usr/小明/diary.html (size : 100)
    /root/usr/小明/Composite.java (size : 200)
    /root/usr/小红 (size : 900)
    /root/usr/小红/game.doc (size : 400)
    /root/usr/小红/junk.mail (size : 500)
    /root/usr/小花 (size : 300)
    /root/usr/小花/memo.tex (size : 300)
    */
    

    角色

    Component:是Leaf和Composite角色的父类,包含这两个角色具有的一致性的信息。在本例中由Entry扮演此角色。

    Leaf:表示内容的角色,里面不能再放入其他对象。本例中由File来扮演此角色。

    Composite:表示容器的角色,里面可以放入Leaf或Composite角色。本例中由Directory扮演此角色。

    Client:使用Composite模式的角色,本例中由Main来扮演。

    UML

    想法

    这个模式非常能体现递归的思想。Composite继承并组合了Component,好好体会一下。

  • 相关阅读:
    产品管理:启示录 特约客户、产品验证、原型测试
    我对敏捷个人培训的“三不原则”
    《敏捷个人》周刊 第2期 (可下载)
    《敏捷个人》周刊 第7期 (可下载)
    敏捷个人2012.6月份线下活动报道:与北邮学子交流职业和成长
    《敏捷个人》周刊 第11期 (可下载)
    敏友的【敏捷个人】有感(15): 初探敏捷个人和敏捷开发的感想
    敏友的【敏捷个人】有感(14): 敏捷个人管理的历程
    从0开始在Android下开发生活方向盘应用(自绘雷达图)
    OpenExpressApp:OEA框架 2.9 PreAlpha 源码公布
  • 原文地址:https://www.cnblogs.com/qianbixin/p/10992961.html
Copyright © 2020-2023  润新知