zoukankan      html  css  js  c++  java
  • 设计模式学习总结(十)--组合模式

    定义

    组合模式又叫部分-整体模式,组合多个对象形成树形结构以表示“整体-部分”的结构层次。

    组合模式对单个对象(叶子对象)和组合对象(组合对象)具有一致性,它将对象组织到树结构中,可以用来描述整体与部分的关系。同时它也模糊了简单元素(叶子对象)和复杂元素(容器对象)的概念,使得客户能够像处理简单元素一样来处理复杂元素,从而使客户程序能够与复杂元素的内部结构解耦。

    组合模式包含角色:

    • Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理 Component 子部件。

    • Leaf:叶子对象。叶子结点没有子结点。

    • Composite:容器对象,定义有枝节点行为,用来存储子部件,在 Component 接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

    从模式结构中我们看出了叶子节点和容器对象都实现 Component 接口,这也是能够将叶子对象和容器对象一致对待的关键所在。

    优缺点

    优点:

    • 更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

    • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。

    • 客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。

    • 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。

    缺点

    • 使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联

    实例

    以文件系统为例。

    定义文件抽象类:

    public abstract class File {
    
        public File(String name){
            this.name = name;
        }
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public abstract void display();
    }
    

    文本文件、图像文件、视频文件对象:

    public class TestFile extends File {
        public TestFile(String name) {
            super(name);
        }
    
        @Override
        public void display() {
            System.out.println("文本文件,文件名:" + super.getName());
        }
    }
    
    public class ImageFile extends File {
        public ImageFile(String name) {
            super(name);
        }
    
        @Override
        public void display() {
            System.out.println("图像文件,文件名:" + super.getName());
        }
    }
    
    public class VideoFile extends File {
        public VideoFile(String name) {
            super(name);
        }
    
        @Override
        public void display() {
            System.out.println("视频文件,文件名:" + super.getName());
        }
    }
    

    文件夹对象:

    public class Folder extends File {
    
        private List<File> fileList = new ArrayList<>();
    
        public Folder(String name) {
            super(name);
        }
    
        /**
         * @desc 向文件夹中添加文件
         * @param file
         * @return void
         */
        public void add(File file){
            fileList.add(file);
        }
    
        /**
         * @desc 从文件夹中删除文件
         * @param file
         * @return void
         */
        public void remove(File file){
            fileList.remove(file);
        }
        /**
         * 浏览文件夹中的文件
         */
        @Override
        public void display() {
            for(File file : fileList){
                file.display();
            }
        }
    
    }
    

    调用:

    public static void main(String[] args) {
        // 组装文本目录
        Folder testFolder = new Folder("文本目录");
        testFolder.add(new TestFile("文本文件1"));
        testFolder.add(new TestFile("文本文件2"));
    
        // 组装图片目录
        Folder imageFolder = new Folder("图片目录");
        imageFolder.add(new ImageFile("图片文件1"));
        imageFolder.add(new ImageFile("图片文件2"));
    
        // 组装视频目录
        Folder videoFolder = new Folder("视频目录");
        videoFolder.add(new VideoFile("视频文件1"));
        videoFolder.add(new VideoFile("视频文件2"));
    
        // 组装根目录
        Folder rootFolder = new Folder("根目录");
        rootFolder.add(testFolder);
        rootFolder.add(imageFolder);
        rootFolder.add(videoFolder);
    
        // 浏览目录
        System.out.println("=========浏览根目录=========");
        rootFolder.display();
        System.out.println("=========浏览文本目录=========");
        testFolder.display();
        System.out.println("=========浏览图片目录=========");
        imageFolder.display();
        System.out.println("=========浏览视频目录=========");
        videoFolder.display();
    }
    

    控制台输出:

    =========浏览根目录=========
    文本文件,文件名:文本文件1
    文本文件,文件名:文本文件2
    图像文件,文件名:图片文件1
    图像文件,文件名:图片文件2
    视频文件,文件名:视频文件1
    视频文件,文件名:视频文件2
    =========浏览文本目录=========
    文本文件,文件名:文本文件1
    文本文件,文件名:文本文件2
    =========浏览图片目录=========
    图像文件,文件名:图片文件1
    图像文件,文件名:图片文件2
    =========浏览视频目录=========
    视频文件,文件名:视频文件1
    视频文件,文件名:视频文件2
    
  • 相关阅读:
    (spring-第15回【IoC基础篇】)容器事件
    javascript笔记2-引用类型
    php namespace use 命名空间
    mysql性能优化(二)
    mysql常用命令
    关于有效的性能调优的一些建议[转]
    apache htaccess
    php 换行 空格分割处理
    一些比较好的博文
    php & 引用
  • 原文地址:https://www.cnblogs.com/markLogZhu/p/11582573.html
Copyright © 2011-2022 走看看