当前位置: 首页 > news >正文

Head First设计模式(阅读笔记)-11.组合模式

继续修改菜单

在迭代器模式中往菜单中加入了迭代器,但是存在一个问题服务员在打印菜单时,每次增加一份菜单就要修改代码,违反开闭原则:

public void printMenu(){
    Iterator pancakeIterator = pancakeHouseMenu.createIterator();
    Iterator cafeIterator = cafeMenu.createIterator();
    printMenu(pancakeIterator);
    printMenu(cafeIterator);
}

为什么不尝试将所有菜单放入一个集合中?

public class Waitress{
    ArrayList menus;  // 统一到一个菜单集合中,该菜单集合包含多种菜单
    public Waitress(ArrayList menus){
        this.menus = menus;
    }
    public void printMenu(){
        // 在菜单集合上进行遍历
        Iterator menuIterator = menus.iterator();
        while(menuIterator.hasNext()){
            Menu menu = (Menu)menuIterator.next();
            printMenu(menu.createIterator());
        }
    }
    private void printMenu(Iterator iterator){
        while(iterator.hasNext()){
            MenuItem item = (Menuitem)iterator.next();
            // 打印操作,此处省略
        }
    }
}

上述方法很好解决了问题,但是此时要在咖啡厅菜单中加入一个甜点菜单,这个甜点菜单是一份单独的菜单,并不是将甜点项(菜单项)添加到咖啡厅菜单中,该如何实现?


组合模式

  • 允许将对象组合为树形结构来表现整体/部分层次结构,树中包含了组合以及个别对象(即叶子节点和非叶子节点)
  • 组合能让客户通过一致的方式处理个别对象和对象组合(即实现相同的接口)

实现菜单组件

菜单组件可以是某个菜单项(叶子节点),也可以是某个菜单(组合,也就是非叶子节点)


public abstract class MenuComponent{
    // 下面方法有些只对菜单项(叶子节点)有意义,有些只对菜单(组合,也就是非叶子节点)有意义,所以默认实现抛出异常
    public void add(MenuComponent menuComponent){  // 新增菜单组件
        throw new UnsupporteOperationException();
    }
    public void remove(MenuComponent menuComponent){  // 删除菜单组件
        throw new UnsupporteOperationException();
    }
    public MenuComponent getChild(int i){  // 获取菜单组件
        throw new UnsupporteOperationException();
    }
    // 还有getName、getPrice等方法,此处省略
}

实现菜单项


public class MenuItem extends MenuComponent{
    String name;
    double price;
    public MenuItem(String name, double price){
        this.name = name;
        this.price = price;
    }
    // 还有getName、getPrice方法,此处省略
    public void print(){
        // 打印菜品名称和价格,此处省略
    }
}

实现组合菜单

对于组合菜单还可以有多个菜单项(叶子节点)以及其他菜单(即子树)


public class Menu extends MenuComponent{
    ArrayList menuComponents = new ArrayList();  // 可以有任意数目的孩子,但是都必须是MenuComponent类型
    String name;
    String desc;
    public MenuItem(String name, String desc){
        this.name = name;
        this.desc = desc;
    }
    public void add(MenuComponent menuComponent){
        menuComponents.add(menuComponent);
    }
    public void remove(MenuComponent menuComponent){
        menuComponents.remove(menuComponent);
    }
    public MenuComponent getChild(int i){
        return (MenuComponent)menuComponents.get(i);
    }
    // 还有getName、getDesc方法,此处省略
    public void print(){
        // 打印菜单名称和描述,此处省略
        // 除了菜单本身信息,还要打印出菜单中所有组件的信息(即其他菜单和菜单项)
        Iterator iterator = menuComponents.iterator();
        while(iterator.hasNext()){
            MenuComponent menuComponent = (MenuComponent)iterator.next();
            menuComponent.print();  // 递归调用
        }
    }
}

修改服务员代码

把最顶层的菜单组件(即整个树的根节点)给服务员


public class Waitress{
    MenuComponent rootmenu;  // 将根节点的交给服务员即可
    public Waitress(MenuComponent rootmenu){
        this.rootmenu = rootmenu;
    }
    public void printMenu(){
        rootmenu.print();
    }
}

测试


public class MenuTest{
    public static void main(String[] agrs){
        // 定义菜单组件(根节点也是菜单组件)
        MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner");        		 
        MenuComponent pancakeHouseMenu = new Menu("PNCAKE HOUSE MENU", "Breakfast");
        MenuComponent dessertMenu = new Menu("DESSRET MENU", "Anytime");
        MenuComponent rootMenu = new Menu("ALL MENUS", "All menus combined");
        
        // 开始构建树
        // 1.添加子树
        rootMenu.add(cafeMenu);
        rootMenu.add(pancakeHouseMenu);
        // 2.往子树中添加叶子节点或其他子树
        cafeMenu.add(dessertMenu);  // 实现开始的目标:往咖啡厅菜单中添加甜点菜单
        cafeMenu.add(new MenuItem("BLACK COFFEE", 25));  // 咖啡厅肯定需要咖啡的
        
        // 把完整菜单给服务员
        Waitress waitress = new Waitress(rootMenu);  
		waitress.printMenu();
    }
}

已学模式


模式描述
适配器模式改变一个或多个接口
迭代器模式提供一个方式遍历集合,且无需暴露集合的实现
外观模式简化一群类的接口
组合模式客户可将对象的集合和个别对象一视同仁
观察者模式当某个对象改变时,允许一群对象被通知

参考

Head First 设计模式-组合模式

设计模式-组合模式

相关文章:

  • 手把手教你成为荣耀开发者:数据报表使用指引
  • java计算机毕业设计企业人事管理系统源程序+mysql+系统+lw文档+远程调试
  • HDFS的概念及shell操作
  • Spring Web 应用程序中的 Flash 属性指南
  • 虚拟机共享物理机网路的NAT连接方法
  • Netty入门——基于NIO实现机器客服案例
  • Maven项目管理工具
  • 探索可观测性:AIOps中的时序数据应用
  • RISCV:cv_regress
  • 计算机毕业设计Java校园管理系统(系统+源码+mysql数据库+lw文档)
  • (附源码)Springboot中北创新创业官网 毕业设计 271443
  • Go语学习笔记 - 实现将mp4通过rtmp推送流媒体服务
  • 读取HDFS数据写入MySQL_大数据培训
  • MySQL日志管理(十一)
  • 前端一面经典vue面试题(持续更新中)
  • leetcode 638. 大礼包-思路整理
  • [附源码]Python计算机毕业设计Django新冠疫苗接种预约系统
  • “无所不能”的 ChatGPT,正准备把各行各业打得满地找牙
  • Mac系统安装Kafka 3.x及可视化工具
  • HTML学生个人网站作业设计:HTML做一个公司官网首页页面(纯html代码)
  • 电加热油锅炉工作原理_电加热导油
  • 大型电蒸汽锅炉_工业电阻炉
  • 燃气蒸汽锅炉的分类_大连生物质蒸汽锅炉
  • 天津市维修锅炉_锅炉汽化处理方法
  • 蒸汽汽锅炉厂家_延安锅炉厂家
  • 山西热水锅炉厂家_酒店热水 锅炉
  • 蒸汽锅炉生产厂家_燃油蒸汽发生器
  • 燃煤锅炉烧热水_张家口 淘汰取缔燃煤锅炉
  • 生物质锅炉_炉
  • 锅炉天然气_天燃气热风炉