• java设计模式——组合模式


    一. 定义与类型

    定义:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使客户端对单个对象和组合对象保持一致的方式处理

    类型:结构性

    假设有一个树形结构的菜单,而在菜单中还可能有子菜单,子菜单下还可能有子菜单,子菜单下还有文件等等, 这种情况下可以使用组合模式。

    二. 使用场景

    (1) 希望客户端可以忽略组合对象与单个对象的差异

    (2) 处理一个树形结构

    三. 优缺点

    优点:

      (1) 清楚的定义层次的复杂对象,表示对象的全部或部分层次

      (2) 让客户端忽略了层次的差异,方便对整个层次结构进行控制

      (3) 简化客户端代码

      (4) 符合开闭原则

    缺点:

      (1) 限制类型时会较为复杂

      (2) 使设计变得更加抽象

    四. 相关设计模式

     组合模式和访问者模式

      可以使用访问者模式来访问组合模式的递归结构

    五. Coding

    以课程目录与课程为例,课程目录有目录名称,课程有名称与价格,它们不是同一类实体,但是它们可以组合成整体一套课程。

    创建一个目录组件类:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-12 11:36
     **/
    public abstract class CatalogComponent {
        public void add(CatalogComponent catalogComponent) {
            throw new UnsupportedOperationException("不支持添加操作");
        }
        public void remove(CatalogComponent catalogComponent) {
            throw new UnsupportedOperationException("不支持删除操作");
        }
        public String getName(CatalogComponent catalogComponent) {
            throw new UnsupportedOperationException("不支持获取名称操作");
        }
        public double getPrice(CatalogComponent catalogComponent) {
            throw new UnsupportedOperationException("不支持获取价格操作");
        }
        public void print() {
            throw new UnsupportedOperationException("不支持打印操作");
        }
    }

    创建一个课程类,继承组件类:

    /**
     * @program: designModel
     * @description: 课程类
     * @author: YuKai Fan
     * @create: 2019-02-12 11:39
     **/
    public class Course extends CatalogComponent {
        private String name;
        private double price;
    
        public Course(String name, double price) {
            this.name = name;
            this.price = price;
        }
    
        @Override
        public String getName(CatalogComponent catalogComponent) {
            return this.name;
        }
    
        @Override
        public double getPrice(CatalogComponent catalogComponent) {
            return this.price;
        }
    
        @Override
        public void print() {
            System.out.println("Course Name:" + name + "Price:" + price);
        }
    }

    在创建一个课程目录类,也继承组件类:

    /**
     * @program: designModel
     * @description: 课程目录类
     * @author: YuKai Fan
     * @create: 2019-02-12 11:41
     **/
    public class CourseCatalog extends CatalogComponent{
        private List<CatalogComponent> items = new ArrayList<CatalogComponent>();
        private String name;public CourseCatalog(String name) {
            this.name = name;
        }
    
        @Override
        public void add(CatalogComponent catalogComponent) {
            items.add(catalogComponent);
        }
    
        @Override
        public void remove(CatalogComponent catalogComponent) {
            items.remove(catalogComponent);
        }
    
        @Override
        public void print() {
            System.out.println(this.name);
            for (CatalogComponent catalogComponent : items) {
               
                        System.out.print(" ");
                    
                }
                catalogComponent.print();
            }
        }
    }

    应用层:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-12 11:47
     **/
    public class Test {
        public static void main(String[] args) {
            CatalogComponent linuxCourse = new Course("Linux课程", 11);
            CatalogComponent windowsCourse = new Course("Windows课程", 15);
    
            CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程");
    
            CatalogComponent mmallCourse1 = new Course("Java电商一期", 55);
            CatalogComponent mmallCourse2 = new Course("Java电商二期", 66);
            CatalogComponent designPattern = new Course("Java设计模式", 77);
    
            javaCourseCatalog.add(mmallCourse1);
            javaCourseCatalog.add(mmallCourse2);
            javaCourseCatalog.add(designPattern);
    
            CatalogComponent mainCourseCatalog = new CourseCatalog("课程主目录");
            mainCourseCatalog.add(linuxCourse);
            mainCourseCatalog.add(windowsCourse);
            mainCourseCatalog.add(javaCourseCatalog);
    
            mainCourseCatalog.print();
    
    
        }
    }

    结果:

    课程主目录
     Course Name:Linux课程Price:11.0
     Course Name:Windows课程Price:15.0
     Java课程
     Course Name:Java电商一期Price:55.0
     Course Name:Java电商二期Price:66.0
     Course Name:Java设计模式Price:77.0
    
    Process finished with exit code 0

    从上面的结果可以看出,java课程与课程主目录都属于目录,只不过等级不同,所以需要根据等级来动态的判断。例如一级目录,二级目录等等。

    这些事组合模式的缺点,限制类型时会比较复杂。所以将上面代码进行改进。

    课程目录类:

    /**
     * @program: designModel
     * @description: 课程目录类
     * @author: YuKai Fan
     * @create: 2019-02-12 11:41
     **/
    public class CourseCatalog extends CatalogComponent{
        private List<CatalogComponent> items = new ArrayList<CatalogComponent>();
        private String name;
        private Integer level;
    
        public CourseCatalog(String name, Integer level) {
            this.name = name;
            this.level = level;
        }
    
        @Override
        public void add(CatalogComponent catalogComponent) {
            items.add(catalogComponent);
        }
    
        @Override
        public void remove(CatalogComponent catalogComponent) {
            items.remove(catalogComponent);
        }
    
        @Override
        public void print() {
            System.out.println(this.name);
            for (CatalogComponent catalogComponent : items) {
                if (this.level != null) {
                    for (int i = 0; i < this.level; i++) {
                        System.out.print(" ");
                    }
                }
                catalogComponent.print();
            }
        }
    }

    应用层:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-12 11:47
     **/
    public class Test {
        public static void main(String[] args) {
            CatalogComponent linuxCourse = new Course("Linux课程", 11);
            CatalogComponent windowsCourse = new Course("Windows课程", 15);
    
            CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程",2);
    
            CatalogComponent mmallCourse1 = new Course("Java电商一期", 55);
            CatalogComponent mmallCourse2 = new Course("Java电商二期", 66);
            CatalogComponent designPattern = new Course("Java设计模式", 77);
    
            javaCourseCatalog.add(mmallCourse1);
            javaCourseCatalog.add(mmallCourse2);
            javaCourseCatalog.add(designPattern);
    
            CatalogComponent mainCourseCatalog = new CourseCatalog("课程主目录",1);
            mainCourseCatalog.add(linuxCourse);
            mainCourseCatalog.add(windowsCourse);
            mainCourseCatalog.add(javaCourseCatalog);
    
            mainCourseCatalog.print();
    
    
        }
    }

    结果:

    UML类图:

    组合模式将多个对象组合成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。

     六. 源码分析

    (1)jdk

    List中的ArrayList中的addAll()方法,以及HashMap中的putAll方法都是通过继承方式的组合模式体现

    (2)mybatis

    SqlNode接口,该接口有很多的实现类,都是通过组合模式将多个sqlNode结合到一起(有的是组合关系,有的不是)。

  • 相关阅读:
    二维数组实现八皇后问题
    解决Java接口内部类的main()方法无法打印输出的问题
    hbase shell 常见命令
    hbase-0.94 Java API
    JavaMail简单版实验测试
    经典KMP算法C++与Java实现代码
    Hadoop之倒排索引
    哈希哈希
    Servlet和JSP学习指导与实践(三):JSP助阵
    Servlet和JSP学习指导与实践(二):Session追踪
  • 原文地址:https://www.cnblogs.com/FanJava/p/10364322.html
Copyright © 2020-2023  润新知