组合模式(Composite Pattern)又叫作整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型设计模式。

    一颗树一般有三种节点

    • 根节点
    • 树干节点
    • 叶子节点

    根节点和树干节点本质上是一种数据类型。在组合模式中,把树干节点和叶子节点也视为是一种数据类型(实现同一个接口),在调用的时候不需要区分是树干节点还是叶子节点。
    当子系统与其内各个对象层次呈树形结构时,可以使用组合模式让子系统内各个对象层次的行为操作具备一致性。当客户端使用该子系统内任意一个对象时,不用进行区分,直接使用通用操作即可,非常便捷。

    场景:

    • 树状结构
    • 客户端可以忽略组合对象与单个对象的差异

    树枝节点和叶子节点实现用一个接口或继承同一个基类

    透明模式
    Component中声明树干节点和根节点的方法,具体实现由子类重写,客户端无需区分树干节点和叶子节点
    安全模式
    Component中只声明公共的方法,子类各自声明自己的特有方法
    接口定义职责分明,符合单一职责原则和接口隔离原则,但是客户端必须区分树干节点和叶子节点有些操作需要强制类型转换违背了依赖倒置原则
    当系统绝大多数层次都具备想用的公共行为,使用透明模式,当各个层次差异较多或树枝节点层级相对稳定时使用安全模式

    框架
    HashMap的putAll
    Mybatis的sqlNode

    安全模式的demo

    1. package com.company.composite;
    2. public abstract class Component {
    3. protected String name;
    4. public Component(String name) {
    5. this.name = name;
    6. }
    7. public abstract void op();
    8. }
    9. package com.company.composite;
    10. import java.util.ArrayList;
    11. import java.util.List;
    12. public class Composite extends Component {
    13. private List<Component> componentList;
    14. public Composite(String name) {
    15. super(name);
    16. this.componentList = new ArrayList<>();
    17. }
    18. @Override
    19. public void op() {
    20. for(Component component : componentList){
    21. component.op();
    22. }
    23. }
    24. public void add(Component component){
    25. this.componentList.add(component);
    26. }
    27. public void remove(Component component){
    28. this.componentList.remove(component);
    29. }
    30. public void getChild(int index){
    31. this.componentList.get(index);
    32. }
    33. }
    34. package com.company.composite;
    35. public class Leaf extends Component {
    36. public Leaf(String name) {
    37. super(name);
    38. }
    39. @Override
    40. public void op() {
    41. System.out.println(this.name);
    42. }
    43. }

    抽象模式的demo

    1. package com.company.composite;
    2. public abstract class Component {
    3. protected String name;
    4. public Component(String name) {
    5. this.name = name;
    6. }
    7. public void add(Component component){
    8. throw new UnsupportedOperationException();
    9. }
    10. public void remove(Component component){
    11. throw new UnsupportedOperationException();
    12. }
    13. public void getChild(int index){
    14. throw new UnsupportedOperationException();
    15. }
    16. }
    17. package com.company.composite;
    18. import java.util.ArrayList;
    19. import java.util.List;
    20. public class Composite extends Component {
    21. private List<Component> componentList;
    22. public Composite(String name) {
    23. super(name);
    24. this.componentList = new ArrayList<>();
    25. }
    26. @Override
    27. public void op() {
    28. for(Component component : componentList){
    29. component.op();
    30. }
    31. }
    32. @Override
    33. public void add(Component component){
    34. this.componentList.add(component);
    35. }
    36. @Override
    37. public void remove(Component component){
    38. this.componentList.remove(component);
    39. }
    40. @Override
    41. public void getChild(int index){
    42. this.componentList.get(index);
    43. }
    44. }
    45. package com.company.composite;
    46. public class Leaf extends Component {
    47. public Leaf(String name) {
    48. super(name);
    49. }
    50. @Override
    51. public void op() {
    52. System.out.println(this.name);
    53. }
    54. }