组合模式——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 }
原文地址:https://www.cnblogs.com/HectorHou/p/6009745.html