组合模式

2022-05-09 21:13:10 浏览数 (2)

暂时还没遇到需要这种设计模式的情景,笔者一般会把层次结构放到数据库里,用 parentId 来标识父子关系

1. 组合模式(Composite Pattern)

将对象组合成树形结构以表示 “部分-整体” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性

组合模式的组成:

  • 抽象根节点(Component):存放整体的默认行为和属性
  • 树枝节点(Composite):存储叶子节点的集合
  • 叶子节点(Leaf):存放真实对象

2. 流程

这里很像操作系统的文件结构

2.1 Component

代码语言:javascript复制
public abstract class Component {
    protected String name;

    public Component(String name) {
        this.name = name;
    }

    public abstract String hierarchical();

    public abstract void addChild(Component component);

    public abstract void removeChild(Component component);

    public abstract Component getChild(int index);
}

2.2 Composite

代码语言:javascript复制
public class Composite extends Component {

    private List<Component> componentList;

    public Composite(String name) {
        super(name);
        componentList = new ArrayList<>();
    }

    public String hierarchical() {
        StringBuilder builder = new StringBuilder(this.name);
        for (Component component : componentList) {
            builder.append("n");
            builder.append(component.hierarchical());
        }
        return builder.toString();
    }

    @Override
    public void addChild(Component component) {
        componentList.add(component);
    }

    @Override
    public void removeChild(Component component) {
        componentList.remove(component);
    }

    @Override
    public Component getChild(int index) {
        return componentList.get(index);
    }
}

2.3 Leaf

代码语言:javascript复制
public class Leaf extends Component {
    public Leaf(String name) {
        super(name);
    }

    @Override
    public void printAll() {
        System.out.println(this.name);
    }

    @Override
    public void addChild(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void removeChild(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Component getChild(int index) {
        throw new UnsupportedOperationException();
    }
}

2.4 案例

代码语言:javascript复制
public static void main(String[] args) {

    Component root = new Composite("root");

    Component branchA = new Composite("--branchA");
    Component branchB = new Composite("--branchB");

    Component leafA = new Leaf("----leafA");
    Component leafB = new Leaf("----leafB");
    Component leafC = new Leaf("----leafC");

    root.addChild(branchA);
    root.addChild(branchB);

    branchA.addChild(leafA);
    branchA.addChild(leafB);
    branchB.addChild(leafC);

    System.out.println(root.hierarchical());
}

//root
//--branchA
//----leafA
//----leafB
//--branchB
//----leafC

3. 改进

上面的案例中叶子节点也具有根节点的方法,这是不符合逻辑的,可以使用组合模式的安全模式,即改变抽象根节点的方法,而其余不变,这样的话根和叶子的责任就明显了

3.1 修改抽象根节点

代码语言:javascript复制
public abstract class Component {
    protected String name;

    public Component(String name) {
        this.name = name;
    }
}

3.2 文件系统

若是文件系统,那抽象根节点还可以添加下面两个方法

代码语言:javascript复制
public boolean isFile() {
    return this instanceof Leaf;
}

public boolean isDir() {
    return this instanceof Composite;
}

0 人点赞