当前位置:   article > 正文

设计模式-组合模式_组合设计模式菜鸟

组合设计模式菜鸟

组合模式定义

组合模式允许你将对象组合成树形结构来表现部分-整体层次结构。组合让客户可以统一处理个别对象和对象的组合。

分析:这个模式感觉接触的很少,不过感觉也是挺有用的,从上一篇博客中学习了有关迭代器模式的东西,总结就是在看不到内部结构的基础上对其进行遍历。

如果从遍历的角度看,假设我们有两份菜单,要对菜单中的数据进行遍历,这个时候我就可以使用迭代器模式进行考虑遍历,两份菜单对应两个迭代器,同样也有两份菜单类,由于我用了java列表的迭代器,就不用自己再次封装迭代器了,如我给出以下示例:

Menu接口,就是定义了菜单有哪些方法:

  1. public interface Menu {
  2. Iterator<MenuItem> createIterator();
  3. }

两个具体的菜单如下:

  1. public class TeaMenu implements Menu {
  2. private List<MenuItem> teaList;
  3. public TeaMenu(List<MenuItem> teaList) {
  4. this.teaList = teaList;
  5. }
  6. @Override
  7. public Iterator<MenuItem> createIterator() {
  8. return teaList.iterator();
  9. }
  10. }
  11. public class MeatMeun implements Menu {
  12. private List<MenuItem> meatList;
  13. public MeatMeun(List<MenuItem> meatList) {
  14. this.meatList = meatList;
  15. }
  16. @Override
  17. public Iterator<MenuItem> createIterator() {
  18. return meatList.iterator();
  19. }
  20. }

菜单项类如下:

  1. public class MenuItem {
  2. private String name;
  3. private double price;
  4. private String description;
  5. public MenuItem(String name, double price, String description) {
  6. this.name = name;
  7. this.price = price;
  8. this.description = description;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public double getPrice() {
  17. return price;
  18. }
  19. public void setPrice(double price) {
  20. this.price = price;
  21. }
  22. public String getDescription() {
  23. return description;
  24. }
  25. public void setDescription(String description) {
  26. this.description = description;
  27. }
  28. @Override
  29. public String toString() {
  30. return "MenuItem{" +
  31. "name='" + name + '\'' +
  32. ", price=" + price +
  33. ", description='" + description + '\'' +
  34. '}';
  35. }
  36. }

商店类,就是为了展示菜单:

  1. public class Shop {
  2. private Menu teaMenu;
  3. private Menu meatMeun;
  4. public Shop(Menu teaMenu, Menu meatMeun) {
  5. this.teaMenu = teaMenu;
  6. this.meatMeun = meatMeun;
  7. }
  8. public void printMenu(){
  9. Iterator<MenuItem> mIterator = this.meatMeun.createIterator();
  10. Iterator<MenuItem> tIterator = this.teaMenu.createIterator();
  11. while(mIterator.hasNext()){
  12. MenuItem next = mIterator.next();
  13. System.out.println(next);
  14. }
  15. while(tIterator.hasNext()){
  16. MenuItem next = tIterator.next();
  17. System.out.println(next);
  18. }
  19. }
  20. public static void main(String[] args) {
  21. List<MenuItem> meatList = new ArrayList<>();
  22. meatList.add(new MenuItem("猪肉",10,"10块一斤"));
  23. meatList.add(new MenuItem("牛肉",50,"50块一斤"));
  24. meatList.add(new MenuItem("羊肉",60,"60块一斤"));
  25. Menu meatMenu = new MeatMeun(meatList);
  26. List<MenuItem> teaList = new ArrayList<>();
  27. teaList.add(new MenuItem("红豆奶茶",10,"10块一杯"));
  28. teaList.add(new MenuItem("珍珠奶茶",11,"11块一杯"));
  29. teaList.add(new MenuItem("椰果奶茶",12,"12块一杯"));
  30. Menu teaMenu = new MeatMeun(teaList);
  31. Shop shop = new Shop(teaMenu, meatMenu);
  32. shop.printMenu();
  33. }
  34. }

上述使用迭代器模式对商店里的菜单内容进行了遍历,但是会发现一个问题,就是如果商店里的肉类菜单下有子类呢,比如分为生肉和熟肉,生肉下分别是生猪肉,生牛肉,生羊肉,而茶菜单又分为奶茶和果茶,奶茶分别为红豆奶茶,珍珠奶茶,椰果奶茶,果茶分为,草莓果茶,百香果果茶,芒果果茶。

如果按照上述情况,就会出现问题,本来的,茶菜单和肉菜单无法表示这种分类关系,而且上述出现了二级菜单,对于原来的菜单也无法表示这种层级关系,所以这种菜单的设计结构将无法进行扩展,对于商店去处理的时候,代码也无法重构,而且也不应该让代码进行经常性的重构,所以这个时候我们就要考虑组合模式了。那么接下来我们看一看组合模式的类图。

组合模式类图

从上面的类图我们要进行提炼几点内容: 

在这里,我们让所有的类都继承自Component类,然后叶子节点将不包含任何内容,而Composite作为一种分支节点类。所以如果动用组合模式,我们就可以将上述内容衍化成下面这种模式。

所以包含肉菜单和茶菜单的类就是根节点,包含生肉和熟肉的肉菜单就是二级节点,其余都是叶子节点。那么这个改造就很清晰了。 我们用代码给出。

组合模式示例代码

  1. //叶子节点
  2. public class MenuItem extends MenuComponent{
  3. private String name;
  4. private double price;
  5. private String description;
  6. public MenuItem(String name, double price, String description) {
  7. this.name = name;
  8. this.price = price;
  9. this.description = description;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public double getPrice() {
  18. return price;
  19. }
  20. public void setPrice(double price) {
  21. this.price = price;
  22. }
  23. public String getDescription() {
  24. return description;
  25. }
  26. @Override
  27. public void print() {
  28. System.out.println(toString());
  29. }
  30. public void setDescription(String description) {
  31. this.description = description;
  32. }
  33. @Override
  34. public String toString() {
  35. return "MenuItem{" +
  36. "name='" + name + '\'' +
  37. ", price=" + price +
  38. ", description='" + description + '\'' +
  39. '}';
  40. }
  41. }
  42. public abstract class MenuComponent {
  43. public void add(MenuComponent menuComponent){
  44. }
  45. public void remove(MenuComponent menuComponent){
  46. }
  47. public MenuComponent getChild(int i){
  48. return null;
  49. }
  50. abstract String getName();
  51. abstract String getDescription();
  52. abstract void print();
  53. }
  54. //分支节点
  55. public class Menu extends MenuComponent {
  56. private List<MenuComponent> list = new ArrayList<>();
  57. String name;
  58. String description;
  59. public Menu(String name, String description) {
  60. this.name = name;
  61. this.description = description;
  62. }
  63. @Override
  64. public void add(MenuComponent menuComponent) {
  65. list.add(menuComponent);
  66. }
  67. @Override
  68. public void remove(MenuComponent menuComponent) {
  69. list.remove(menuComponent);
  70. }
  71. @Override
  72. public MenuComponent getChild(int i) {
  73. return list.get(i);
  74. }
  75. @Override
  76. String getName() {
  77. return name;
  78. }
  79. @Override
  80. String getDescription() {
  81. return description;
  82. }
  83. @Override
  84. void print() {
  85. System.out.println("\n" + getName());
  86. System.out.println("," + getDescription());
  87. System.out.println("-------------------");
  88. for (MenuComponent m: list) {
  89. m.print();
  90. }
  91. }
  92. }
  93. public class Client {
  94. public static void main(String[] args) {
  95. MenuComponent root = new Menu("菜单","我是菜单");
  96. MenuComponent meat = new Menu("肉类菜单","我是肉类菜单");
  97. MenuComponent ripeMeat = new Menu("熟肉类菜单","我是熟肉类菜单");
  98. ripeMeat.add(new MenuItem("熟羊肉",100,"熟羊肉100元一斤"));
  99. ripeMeat.add(new MenuItem("熟猪肉",30,"熟猪肉30元一斤"));
  100. ripeMeat.add(new MenuItem("熟牛肉",90,"熟牛肉90元一斤"));
  101. MenuComponent rawMeat = new Menu("生肉类菜单","我是生肉类菜单");
  102. rawMeat.add(new MenuItem("生羊肉",50,"生羊肉50元一斤"));
  103. rawMeat.add(new MenuItem("生猪肉",15,"生猪肉15元一斤"));
  104. rawMeat.add(new MenuItem("生牛肉",45,"生牛肉45元一斤"));
  105. meat.add(rawMeat);
  106. meat.add(ripeMeat);
  107. MenuComponent tea = new Menu("茶菜单","我是茶菜单");
  108. MenuComponent milkTea = new Menu("奶茶菜单","我是奶茶菜单");
  109. milkTea.add(new MenuItem("珍珠奶茶",10,"珍珠奶茶10一杯"));
  110. milkTea.add(new MenuItem("红豆奶茶",11,"红豆奶茶11一杯"));
  111. milkTea.add(new MenuItem("椰果奶茶",12,"椰果奶茶12一杯"));
  112. MenuComponent fruitTea = new Menu("果茶菜单","我是果茶菜单");
  113. fruitTea.add(new MenuItem("草莓果茶",15,"草莓果茶15一杯"));
  114. fruitTea.add(new MenuItem("百香果果茶",15,"百香果茶15一杯"));
  115. fruitTea.add(new MenuItem("芒果果茶",15,"芒果果茶15一杯"));
  116. tea.add(milkTea);
  117. tea.add(fruitTea);
  118. root.add(meat);
  119. root.add(tea);
  120. root.print();
  121. }
  122. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/606750
推荐阅读
相关标签
  

闽ICP备14008679号