经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
组合模式
来源:cnblogs  作者:纳兰小依  时间:2019/10/14 10:00:44  对本文有异议

      组合模式允许用户将对象组合成树形结构来表现“整体/部分”的层次结构,从而能够以一致的方式处理单个对象以及对象组合。根据这个定义,首先能够想到的就是软件的菜单,一个菜单可以包含菜单项(菜单项是指不再包含其他内容的菜单条目),也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当,我们的需求是针对一个菜单,打印出其包含的所有菜单以及菜单项。

      首先,不管是菜单还是菜单项,都应该继承自统一的接口,这里姑且将这个统一的接口称为菜单组件,其定义如下:

  1. 1 public abstract class MenuComponent {
  2. 2 public void add(MenuComponent menuComponent){
  3. 3 throw new UnsupportedOperationException();
  4. 4 }
  5. 5
  6. 6 public void remove(MenuComponent menuComponent){
  7. 7 throw new UnsupportedOperationException();
  8. 8 }
  9. 9
  10. 10 public MenuComponent getChild(int i){
  11. 11 throw new UnsupportedOperationException();
  12. 12 }
  13. 13
  14. 14 public String getName(){
  15. 15 throw new UnsupportedOperationException();
  16. 16 }
  17. 17
  18. 18 public String getDescription(){
  19. 19 throw new UnsupportedOperationException();
  20. 20 }
  21. 21
  22. 22 public void print(){
  23. 23 throw new UnsupportedOperationException();
  24. 24 }
  25. 25 }
MenuComponent

      这里选择抽象类来实现MenuComponent,是因为需要对一些方法给出默认实现,如此一来,Menu和MenuItem类就可以只覆盖自己感兴趣的方法,而不用搭理不需要或者不感兴趣的方法,举例来说,Menu类可以包含子菜单,因此需要覆盖add()、remove()、getChild()方法,但是MenuItem就不应该有这些方法。这里给出的默认实现是抛出异常,你也可以根据自己的需要改写默认实现。

      接下来定义菜单类Menu:

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

      Menu类应该覆盖自己感兴趣的方法,实际上这里它覆盖了父类的所有方法,这样做的原因仅仅是因为抽象类中的所有方法都是该类需要的,假设某一天我们在MenuComponent里面增加了color()方法,该方法只针对菜单项显示灰色底色,那么Menu累就不应该覆盖color()方法了。

      让我们接着来实现MenuItem:

  1. 1 public class MenuItem extends MenuComponent{
  2. 2 private String name;
  3. 3 private String descrition;
  4. 4
  5. 5 public MenuItem(String name, String descrition){
  6. 6 this.name = name;
  7. 7 this.descrition = descrition;
  8. 8 }
  9. 9
  10. 10 @Override
  11. 11 public String getName() {
  12. 12 return name;
  13. 13 }
  14. 14
  15. 15 @Override
  16. 16 public String getDescription(){
  17. 17 return descrition;
  18. 18 }
  19. 19
  20. 20 @Override
  21. 21 public void print(){
  22. 22 System.out.println(getName() + ", " + getDescription());
  23. 23 }
  24. 24 }
MenuItem

      MenuItem只覆盖了getName()、getDescription()、print()方法,因为其他的方法对该类并不适用。

      现在可以写个测试类看一下组合模式在菜单上面的表现了:

  1. 1 public class MenuComponentTest {
  2. 2 public static void main(String[] args){
  3. 3 MenuComponentTest test = new MenuComponentTest();
  4. 4 MenuComponent allMenu = test.createMenu();
  5. 5 allMenu.print();
  6. 6 }
  7. 7
  8. 8 public MenuComponent createMenu(){
  9. 9 MenuComponent fileMenu = new Menu("文件", "文件相关选项");
  10. 10 fileMenu.add(new MenuItem("设置", "可以更改一些设置项"));
  11. 11 fileMenu.add(new MenuItem("保存", "保存所有文件"));
  12. 12
  13. 13 MenuComponent saveAsMenu = new Menu("另存为", "另存为其他一些格式");
  14. 14 saveAsMenu.add(new MenuItem("PDF", "另存为PDF格式"));
  15. 15 saveAsMenu.add(new MenuItem("docx","另存为docx格式"));
  16. 16 fileMenu.add(saveAsMenu);
  17. 17
  18. 18 MenuComponent helpMenu = new Menu("帮助","一些辅助项");
  19. 19 helpMenu.add(new MenuItem("关于我们","软件制作方的一些消息"));
  20. 20 helpMenu.add(new MenuItem("帮助中心","电话和邮箱咨询"));
  21. 21
  22. 22 MenuComponent allMenu = new Menu("所有菜单","包含所有菜单的菜单");
  23. 23 allMenu.add(fileMenu);
  24. 24 allMenu.add(helpMenu);
  25. 25
  26. 26 return allMenu;
  27. 27 }
  28. 28 }

      打印结果为(没有缩进所以稍微丑了一点):

  1. 所有菜单, 包含所有菜单的菜单
  2. 文件, 文件相关选项
  3. 设置, 可以更改一些设置项
  4. 保存, 保存所有文件
  5. 另存为, 另存为其他一些格式
  6. PDF, 另存为PDF格式
  7. docx, 另存为docx格式
  8. 帮助, 一些辅助项
  9. 关于我们, 软件制作方的一些消息
  10. 帮助中心, 电话和邮箱咨询

      最后回顾一下这个菜单的例子,类之间的关系如下:

 

原文链接:http://www.cnblogs.com/NaLanZiYi-LinEr/p/11667774.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号