设计模式----组合模式

概述

将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次

涉及角色:

  • omponent
    抽象构件角色:这是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
  • Leaf
    叶子构件 :叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
  • Composite
    树枝构件:定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,如增加(add)和删除(remove)等。

组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因

UML

这里写图片描述

使用场景

  • 需求中是体现部分与整体层次结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了,如树形菜单,文件、文件夹的管理

优点

  • 高层模块调用简单:组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。将”客户代码与复杂的对象容器结构“解耦。
  • 节点自由增加:可以更容易地往组合对象中加入新的构件。

缺点

  • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
  • 使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系

代码示例

透明式组合模式

在Component中声明所有来管理子对象的方法,其中包括add,remove等。这样实现Component接口的所有子类都具备了add和remove方法。这样做的好处是叶节点和枝节点对于外界没有区别,它们具备完全一致的接口

package com.designpattern.Composite;

public abstract class ComponentLucency {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    protected abstract void add(ComponentLucency c);

    protected abstract void remove(ComponentLucency c);

    protected abstract void display(int depth);
}
package com.designpattern.Composite;

import java.util.ArrayList;
import java.util.List;

public class CompositeLucency extends ComponentLucency {
    private List<ComponentLucency> children = new ArrayList<>();

    public CompositeLucency(String name){
        setName(name);
    }

    @Override
    protected void add(ComponentLucency c) {
        children.add(c);
    }

    @Override
    protected void remove(ComponentLucency c) {
        children.remove(c);
    }

    @Override
    protected void display(int depth) {
        String temp = "";
        for (int i=0; i<depth; i++){
            temp += "-";
        }
        System.out.println(temp + getName());

        for (ComponentLucency child : children){
            child.display(depth + 2);
        }
    }
}
package com.designpattern.Composite;

public class LeafLucency extends ComponentLucency {

    public LeafLucency(String name){
        setName(name);
    }

    @Override
    protected void add(ComponentLucency c) {
        //叶子节点不能添加子节点,因此不做实现
    }

    @Override
    protected void remove(ComponentLucency c) {
        //叶子节点不能添加子节点,因此不做实现
    }

    @Override
    protected void display(int depth) {
        String temp = "";
        for (int i=0; i<depth; i++){
            temp += "-";
        }
        System.out.println(temp + getName());
    }
}

弊端:客户端对叶节点和枝节点是一致的,但叶节点并不具备add和remove的功能,因而对它们的实现是没有意义的

安全式组合模式

在Component中不去声明add和remove方法,那么子类的Leaf就不需要实现它,而是在Composit声明所有用来管理子类对象的方法

package com.designpattern.Composite;

public abstract class ComponentSafety {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    protected abstract void display(int depth);
}
package com.designpattern.Composite;

import java.util.ArrayList;
import java.util.List;

public class CompositeSafety extends ComponentSafety {
    private List<ComponentSafety> children = new ArrayList<>();

    public CompositeSafety(String name){
        setName(name);
    }
    protected void add(ComponentSafety c) {
        children.add(c);
    }

    protected void remove(ComponentSafety c) {
        children.remove(c);
    }

    @Override
    protected void display(int depth) {
        String temp = "";
        for (int i=0; i<depth; i++){
            temp += "-";
        }
        System.out.println(temp + getName());

        for (ComponentSafety child : children){
            child.display(depth + 2);
        }
    }
}
package com.designpattern.Composite;

public class LeafSafety extends ComponentSafety {

    public LeafSafety(String name){
        setName(name);
    }

    @Override
    protected void display(int depth) {
        String temp = "";
        for (int i=0; i<depth; i++){
            temp += "-";
        }
        System.out.println(temp + getName());
    }
}

叶节点无需在实现add与remove这样的方法,但是对于客户端来说,必须对叶节点和枝节点进行判定,为客户端的使用带来不便

测试主函数

package com.designpattern.Composite;

public class TestMain {
    public static void main(String[] args) {

        //透明式组合模式
        ComponentLucency rootLucency = new CompositeLucency("根节点");

        ComponentLucency rootChildX = new CompositeLucency("根节点的X节点");
        ComponentLucency rootChildY = new CompositeLucency("根节点的Y节点");

        rootLucency.add(rootChildX);
        rootLucency.add(rootChildY);

        rootChildX.add(new LeafLucency("X节点-叶子"));
        rootChildX.add(new LeafLucency("X节点-叶子"));

        rootChildY.add(new LeafLucency("Y节点—叶子"));

        rootLucency.display(1);


        //安全式组合模式
        CompositeSafety rootSafe = new CompositeSafety("Root");

        CompositeSafety branchX = new CompositeSafety("Branch X in Root");
        CompositeSafety branchY = new CompositeSafety("Branch Y in Root");

        rootSafe.add(branchX);
        rootSafe.add(branchY);

        branchX.add(new LeafSafety("Leaf A in Branch X"));
        branchX.add(new CompositeSafety("Leaf B in Branch X"));

        branchY.add(new LeafSafety("Leaf C in Branch Y"));

        rootSafe.display(1);


    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值