• 组合模式——HeadFirst设计模式学习笔记


    组合模式:允许将对象组合成树形结构来表现“整体/部分”层次结构。组合让客户用一致的方式处理个别对象和组合对象

    特点:

    • 树形结构表示对象组合
    • 忽略对象组合和对象个体之间的差别,即相同的操作既可以作用于对象组合,也可以作用与对象个体

    注意:

    • 因为继承方法中,有些方法只有对叶子节点有意义,而有些方法只对非叶子节点有意义,我们可以将基类的方法默认实现为抛出UnsupportedOperationException,如果方法无意义,则无需修改默认继承就可以了

    透明性:

    • 组合模式以单一责任原则换取了透明性
    • 通过让组件接口同时包含叶子节点和非叶子节点的操作,客户可以将叶子节点和非叶子节点一视同仁,客户不知道节点的类别
    • 换取透明性的同时我们同样失去了一些安全性

    举例:

    实现菜单中的每一項可以是菜单也可以是菜单项

    抽象基类包括叶子节点和非叶子节点的全部操作默认实现为Exception

     1 public abstract class MenuComponent  
     2 {  
     3     //对一些方法进行了默认实现  
     4     public void add(MenuComponent menuComponent)  
     5     {  
     6         throw new UnsupportedOperationException();  
     7     }  
     8     public void remove(MenuComponent menuComponent)  
     9     {  
    10         throw new UnsupportedOperationException();  
    11     }  
    12     public MenuComponent getChild(int i)  
    13     {  
    14         throw new UnsupportedOperationException();  
    15     }  
    16     public String getName()  
    17     {  
    18         throw new UnsupportedOperationException();  
    19     }  
    20     public String getDescription()  
    21     {  
    22         throw new UnsupportedOperationException();  
    23     }  
    24     public double getPrice()  
    25     {  
    26         throw new UnsupportedOperationException();  
    27     }  
    28     public boolean isVegetarian()  
    29     {  
    30         throw new UnsupportedOperationException();  
    31     }  
    32     public void print()  
    33     {  
    34         throw new UnsupportedOperationException();  
    35     }  
    36 }  

    菜单项实现,即叶子节点实现

     1 public class MenuItem extends MenuComponent  
     2 {  
     3     String name;  
     4     String description;  
     5     boolean vegetarian;  
     6     double price;  
     7   
     8     public MenuItem(String name, String description, boolean vegetarian,double price)  
     9     {  
    10         this.name = name;  
    11         this.description = description;  
    12         this.vegetarian = vegetarian;  
    13         this.price = price;  
    14     }   
    15     public String getName()  
    16     {  
    17         return name;  
    18     }  
    19     public String getDescription()  
    20     {  
    21         return description;  
    22     }  
    23     public double getPrice()  
    24     {  
    25         return price;  
    26     }  
    27     public boolean isVegetarian()  
    28     {  
    29         return vegetarian;  
    30     }  
    31     public void print()  
    32     {  
    33         System.out.print("  " + getName());  
    34         if (isVegetarian())//素食  
    35         {  
    36             System.out.print("(v)");  
    37         }  
    38         System.out.println(", " + getPrice());  
    39         System.out.println("     -- " + getDescription());  
    40     }  
    41 }  

    菜单实现,即非叶子节点的实现:

     1 public class Menu extends MenuComponent  
     2 {  
     3     ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();  
     4     String name;  
     5     String description;  
     6   
     7     public Menu(String name, String description)  
     8     {  
     9         this.name = name;  
    10         this.description = description;  
    11     }  
    12   
    13     public void add(MenuComponent menuComponent)  
    14     {  
    15         menuComponents.add(menuComponent);  
    16     }  
    17   
    18     public void remove(MenuComponent menuComponent)  
    19     {  
    20         menuComponents.remove(menuComponent);  
    21     }  
    22   
    23     public MenuComponent getChild(int i)  
    24     {  
    25         return  menuComponents.get(i);  
    26     }  
    27   
    28     public String getName()  
    29     {  
    30         return name;  
    31     }  
    32   
    33     public String getDescription()  
    34     {  
    35         return description;  
    36     }  
    37   
    38     public void print()  
    39     {  
    40         System.out.print("
    " + getName());  
    41         System.out.println(", " + getDescription());  
    42         System.out.println("---------------------");  
    43   
    44         Iterator iterator = menuComponents.iterator();  
    45         while (iterator.hasNext())  
    46         {  
    47             MenuComponent menuComponent = (MenuComponent) iterator.next();  
    48             menuComponent.print();  
    49         }  
    50     }  
    51 }

    组合迭代器:

     1 public class CompositeIterator implements Iterator<MenuComponent> {
     2 
     3     Stack<Iterator<MenuComponent>> stack = new Stack<Iterator<MenuComponent>>();
     4     
     5 
     6     public CompositeIterator(Iterator<MenuComponent> iterator) {
     7         stack.push(iterator);
     8     }
     9     
    10     public boolean hasNext() {
    11         if (stack.empty()) {
    12             return false;
    13         } else {
    14             Iterator<MenuComponent> iterator = (Iterator<MenuComponent>)stack.peek();
    15             if (!iterator.hasNext()) {
    16                 stack.pop();
    17                 return hasNext(); //递归调用
    18             } else {
    19                 return true;
    20             }
    21         }
    22     }
    23     
    24     public MenuComponent next() {
    25         if (hasNext()) {
    26             Iterator<MenuComponent> iterator = (Iterator<MenuComponent>)stack.peek();
    27             MenuComponent component = (MenuComponent)iterator.next();
    28             if (component instanceof Menu) {
    29                 stack.push(component.createIterator());
    30             }
    31             return component;
    32         } else {
    33             return null;
    34         }
    35     }
    36 
    37     public void remove() {
    38         throw new UnsupportedOperationException();
    39     }
    40     
    41 }
  • 相关阅读:
    【QML Model-View】ListView-简单使用(一)
    QML 界面切换的几种方法(带示例代码)
    QML 常用控件:TextInput, TextField, TextEdit, TextArea(编辑框)用法及自定义
    props参数赋值给data
    nprogress 跳转路由进度条
    小程序页面加水印
    el-table默认展示所有行
    父子路由传参
    IE接口缓存
    wireshark抓包新手使用教程
  • 原文地址:https://www.cnblogs.com/HectorHou/p/6009745.html
Copyright © 2020-2023  润新知