Java设计模式之组合模式

组合模式

定义

以下引用来自于《head first 设计模式》第九章

组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。

组合能让客户以一致的方式处理个别对象以及对象组合。

优缺点

以下引用来自于参考1

组合模式的主要优点有:

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  2. 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

其主要缺点是:

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  2. 不容易限制容器中的构件;
  3. 不容易用继承的方法来增加构件的新功能;

使用场景

以下引用来自于参考1

  1. 在需要表示一个对象整体与部分的层次结构的场合。
  2. 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。

示例

以下代码来自于《head first 设计模式》第九章

菜单组件

public abstract class MenuComponent {
   
   public void add(MenuComponent menuComponent) {
      throw new UnsupportedOperationException();
   }
   public void remove(MenuComponent menuComponent) {
      throw new UnsupportedOperationException();
   }
   public MenuComponent getChild(int i) {
      throw new UnsupportedOperationException();
   }
  
   public String getName() {
      throw new UnsupportedOperationException();
   }
   public String getDescription() {
      throw new UnsupportedOperationException();
   }
   public double getPrice() {
      throw new UnsupportedOperationException();
   }
   public boolean isVegetarian() {
      throw new UnsupportedOperationException();
   }
  
   public void print() {
      throw new UnsupportedOperationException();
   }
}

菜单项 扩展MenuComponent

public class MenuItem extends MenuComponent {
    String name;
    String description;
    boolean vegetarian;
    double price;

    public MenuItem(String name, String description, boolean vegetarian, double price) {
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public double getPrice() {
        return price;
    }

    @Override
    public boolean isVegetarian() {
        return vegetarian;
    }

    @Override
    public void print() {
        System.out.print("  " + getName());
        if (isVegetarian()) {
            System.out.print("(v)");
        }
        System.out.println(", " + getPrice());
        System.out.println("     -- " + getDescription());
    }
}

组合菜单

public class Menu extends MenuComponent {
   ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
   String name;
   String description;
  
   public Menu(String name, String description) {
      this.name = name;
      this.description = description;
   }
 
   @Override
   public void add(MenuComponent menuComponent) {
      menuComponents.add(menuComponent);
   }
 
   @Override
   public void remove(MenuComponent menuComponent) {
      menuComponents.remove(menuComponent);
   }
 
   @Override
   public MenuComponent getChild(int i) {
      return (MenuComponent)menuComponents.get(i);
   }
 
   @Override
   public String getName() {
      return name;
   }
 
   @Override
   public String getDescription() {
      return description;
   }
 
   @Override
   public void print() {
      System.out.print("\n" + getName());
      System.out.println(", " + getDescription());
      System.out.println("---------------------");
  
      Iterator<MenuComponent> iterator = menuComponents.iterator();
      while (iterator.hasNext()) {
         MenuComponent menuComponent = 
            (MenuComponent)iterator.next();
         menuComponent.print();
      }
   }
}

测试菜单使用

public class MenuTestDrive {
   public static void main(String args[]) {
      MenuComponent pancakeHouseMenu =
            new Menu("PANCAKE HOUSE MENU", "Breakfast");
      MenuComponent dinerMenu =
            new Menu("DINER MENU", "Lunch");
      MenuComponent cafeMenu =
            new Menu("CAFE MENU", "Dinner");
      MenuComponent dessertMenu =
            new Menu("DESSERT MENU", "Dessert of course!");
      MenuComponent coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee");

      MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");

      allMenus.add(pancakeHouseMenu);
      allMenus.add(dinerMenu);
      allMenus.add(cafeMenu);

      pancakeHouseMenu.add(new MenuItem(
            "K&B's Pancake Breakfast",
            "Pancakes with scrambled eggs and toast",
            true,
            2.99));
      pancakeHouseMenu.add(new MenuItem(
            "Regular Pancake Breakfast",
            "Pancakes with fried eggs, sausage",
            false,
            2.99));
      pancakeHouseMenu.add(new MenuItem(
            "Blueberry Pancakes",
            "Pancakes made with fresh blueberries, and blueberry syrup",
            true,
            3.49));
      pancakeHouseMenu.add(new MenuItem(
            "Waffles",
            "Waffles with your choice of blueberries or strawberries",
            true,
            3.59));

      dinerMenu.add(new MenuItem(
            "Vegetarian BLT",
            "(Fakin') Bacon with lettuce & tomato on whole wheat",
            true,
            2.99));
      dinerMenu.add(new MenuItem(
            "BLT",
            "Bacon with lettuce & tomato on whole wheat",
            false,
            2.99));
      dinerMenu.add(new MenuItem(
            "Soup of the day",
            "A bowl of the soup of the day, with a side of potato salad",
            false,
            3.29));
      dinerMenu.add(new MenuItem(
            "Hot Dog",
            "A hot dog, with saurkraut, relish, onions, topped with cheese",
            false,
            3.05));
      dinerMenu.add(new MenuItem(
            "Steamed Veggies and Brown Rice",
            "Steamed vegetables over brown rice",
            true,
            3.99));

      dinerMenu.add(new MenuItem(
            "Pasta",
            "Spaghetti with marinara sauce, and a slice of sourdough bread",
            true,
            3.89));

      dinerMenu.add(dessertMenu);

      dessertMenu.add(new MenuItem(
            "Apple Pie",
            "Apple pie with a flakey crust, topped with vanilla icecream",
            true,
            1.59));

      dessertMenu.add(new MenuItem(
            "Cheesecake",
            "Creamy New York cheesecake, with a chocolate graham crust",
            true,
            1.99));
      dessertMenu.add(new MenuItem(
            "Sorbet",
            "A scoop of raspberry and a scoop of lime",
            true,
            1.89));

      cafeMenu.add(new MenuItem(
            "Veggie Burger and Air Fries",
            "Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
            true,
            3.99));
      cafeMenu.add(new MenuItem(
            "Soup of the day",
            "A cup of the soup of the day, with a side salad",
            false,
            3.69));
      cafeMenu.add(new MenuItem(
            "Burrito",
            "A large burrito, with whole pinto beans, salsa, guacamole",
            true,
            4.29));

      cafeMenu.add(coffeeMenu);

      coffeeMenu.add(new MenuItem(
            "Coffee Cake",
            "Crumbly cake topped with cinnamon and walnuts",
            true,
            1.59));
      coffeeMenu.add(new MenuItem(
            "Bagel",
            "Flavors include sesame, poppyseed, cinnamon raisin, pumpkin",
            false,
            0.69));
      coffeeMenu.add(new MenuItem(
            "Biscotti",
            "Three almond or hazelnut biscotti cookies",
            true,
            0.89));

      Waitress waitress = new Waitress(allMenus);

      waitress.printMenu();
   }
}

参考

1组合模式(详解版)

2《head first 设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值