• 设计模式——组合模式


    组合模式的一般定义:将对象组合成树形结构,表示整体!对于使用者来说,单个对象和整体是一致的。

    组合模式一般在树形结构(层次结构)中应用较多,例如:菜单结构,文件夹结构;一般情况下是整体与单个对象具有很大的相似性;

    使用组合模式实现菜单管理:

    首先定义菜单的抽象类:

    /*
     * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
     */
    
    package com.pt.composite;
    
    /**
     * @description 定义一个抽象的menu对象
     * @author panteng
     * @date 17-2-15.
     */
    public abstract class AbstractMenu {
        String menuName;
        protected Integer menuLevel;
        public AbstractMenu(){
        }
    
        public AbstractMenu(String name){
            this.menuName = name;
        }
    
        public abstract void clickEvent();
        public abstract void add(AbstractMenu abstractMenu);
        public abstract void remove(AbstractMenu abstractMenu);
    
        public String getMenuName(){
            return menuName;
        }
        public void setMenuName(String menuName){
            this.menuName = menuName;
        }
    
        public Integer getMenuLevel(){
            return menuLevel;
        }
        public void setMenuLevel(Integer menuLevel){
            this.menuLevel = menuLevel;
        }
    }
    AbstractMenu

    定义Menu节点:

    /*
     * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
     */
    
    package com.pt.composite;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @description
     * @author panteng
     * @date 17-2-15.
     */
    public class Menu extends AbstractMenu {
        List<AbstractMenu> childMenus = new ArrayList<AbstractMenu>();
    
        public Menu(){
            super();
        }
        public Menu(String name){
            super(name);
        }
        @Override
        public void clickEvent(){
            for (int i = 0; i < this.menuLevel; i++) {
                System.out.print("- ");
            }
            System.out.println(this.getMenuName());
            for (AbstractMenu menu : childMenus) {
                menu.clickEvent();
            }
        }
        @Override
        public void add(AbstractMenu abstractMenu){
            abstractMenu.menuLevel = this.menuLevel + 1;
            childMenus.add(abstractMenu);
        }
        @Override
        public void remove(AbstractMenu abstractMenu){
            childMenus.remove(abstractMenu);
        }
        @Override
        public String getMenuName(){
            return super.getMenuName();
        }
        @Override
        public void setMenuName(String menuName){
            super.setMenuName(menuName);
        }
    }
    Menu

    定义叶子节点,与menu节点的区别是没有子节点,因此add和remove方法需要特殊处理

    /*
     * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
     */
    
    package com.pt.composite;
    
    /**
     * @description
     * @author panteng
     * @date 17-2-15.
     */
    public class LeafMenu extends AbstractMenu {
        String url;
    
        public LeafMenu(){
            super();
        }
        public LeafMenu(String name){
            super(name);
        }
    
        public LeafMenu(String name, String url){
            this.menuName = name;
            this.url = url;
        }
        @Override
        public void clickEvent(){
            for (int i = 0; i < this.menuLevel; i++) {
                System.out.print("- ");
            }
            System.out.println("访问URL:" + url);
        }
        @Override
        public void add(AbstractMenu abstractMenu){
            abstractMenu.menuLevel = this.menuLevel + 1;
            System.out.println("不支持add");
        }
        @Override
        public void remove(AbstractMenu abstractMenu){
            System.out.println("不支持remove");
        }
    
        public String getUrl(){
            return url;
        }
        public void setUrl(String url){
            this.url = url;
        }
    }
    LeafMenu

    测试代码:

    /*
     * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
     */
    
    package com.pt.composite;
    
    import org.junit.Test;
    
    /**
     * @description
     * @author panteng
     * @date 17-2-15.
     */
    public class CompositeModelTest {
        /**
         *
         */
        @Test
        public void menuTest(){
            System.out.println("开始测试... ...");
            Menu rootMenu = new Menu("根节点");
            rootMenu.setMenuLevel(0);
            Menu menu1 = new Menu("一级节点1");
            Menu menu2 = new Menu("一级节点2");
            Menu menu3 = new Menu("一级节点3");
            rootMenu.add(menu1);
            rootMenu.add(menu2);
            rootMenu.add(menu3);
    
            Menu menu11 = new Menu("二级节点11");
            Menu menu12 = new Menu("二级节点12");
            menu1.add(menu11);
            menu1.add(menu12);
    
            Menu menu21 = new Menu("二级节点21");
            Menu menu22 = new Menu("二级节点22");
            menu2.add(menu21);
            menu2.add(menu22);
    
            Menu menu31 = new Menu("二级节点31");
            Menu menu32 = new Menu("二级节点32");
            menu3.add(menu31);
            menu3.add(menu32);
    
            LeafMenu leafMenu111 = new LeafMenu("叶子节点111", "网址1");
            LeafMenu leafMenu112 = new LeafMenu("叶子节点112", "网址2");
            menu11.add(leafMenu111);
            menu11.add(leafMenu112);
            LeafMenu leafMenu121 = new LeafMenu("叶子节点121", "网址3");
            menu12.add(leafMenu121);
            LeafMenu leafMenu211 = new LeafMenu("叶子节点211", "网址4");
            menu21.add(leafMenu211);
            LeafMenu leafMenu221 = new LeafMenu("叶子节点221", "网址5");
            menu22.add(leafMenu221);
            LeafMenu leafMenu311 = new LeafMenu("叶子节点311", "网址6");
            menu31.add(leafMenu311);
    
            rootMenu.clickEvent();
        }
    }
    CompositeModelTest

    输出结果:

    开始测试... ...
    根节点
    - 一级节点1
    - - 二级节点11
    - - - 访问URL:网址1
    - - - 访问URL:网址2
    - - 二级节点12
    - - - 访问URL:网址3
    - 一级节点2
    - - 二级节点21
    - - - 访问URL:网址4
    - - 二级节点22
    - - - 访问URL:网址5
    - 一级节点3
    - - 二级节点31
    - - - 访问URL:网址6
    - - 二级节点32

    简单总结一下,使用组合模式,对于客户端的调用很方便!局限性在于,单个对象,和组合后的对象需要有一定的相似性,可以抽象为用户调用的接口,对象多次组合只是量的增长,不会引起质的变化!

    此例中只是两种类型对象的组合,实际应用中可能是多种类型对象的组合!

    .NET的各种控件就应用了组合模式,这么看来

     相关文章:

    http://blog.csdn.net/hfmbook/article/details/7693069

  • 相关阅读:
    leetcode 21 Merge Two Sorted Lists
    leetcode 20 Valid Parentheses
    leetcode 19 Remove Nth Node From End of List
    [学习笔记]守护进程深入理解
    [学习笔记]父进程wait和waitpid
    [学习笔记]进程终止的5种方式
    [学习笔记]父子进程共享文件描述符理解
    [学习笔记]Vfork深入理解
    [学习笔记]_exit和exit深入理解
    [学习笔记]孤儿进程僵死进程
  • 原文地址:https://www.cnblogs.com/tengpan-cn/p/6402062.html
Copyright © 2020-2023  润新知