设计模式之组合模式

组合模式的概念


组合模式是一种结构型设计模式,它允许将对象组成树形结构,以表达“部分-整体” 结构,使得客户端可以使用统一的方式处理单个对象和组合对象。组合模式基于递归结构,将对象组织成一个树形结构,并且客户端对单个对象和组合对象的操作是一致的。组合模式可分为安全式组合模式和透明式组合模式两种,其中:

安全式组合模式中将 leaf 和 composite 的操作分开,即一些复杂的操作只对 composite 开发而不放到 component 中,通过这种方式,客户端只能调用 Composite 自身的操作,而不能调用 Leaf 的操作。

透明式组合模式消除了安全式组合模式的区分,使得 Leaf 和 Composite 具有相同的接口。透明组合模式中的所有子类都定义了 Component 接口中的所有接口,因此,客户端无论处理 Leaf 还是 Composite 时,都可以使用相同的接口,这样使得判断一个节点是组合节点还是叶子节点变得无所谓,这样带来的好处是客户端更加简单、直观。但是透明式组合模式的问题在于叶子节点并不支持添加子节点,这使得叶子节点的某些操作无意义。


组合模式的角色

Component: 组合对象的抽象基类,声明了组合对象的通用接口,定义了一个默认实现的子对象集合;
Leaf: 叶子对象,是组合的最基本对象,不包含任何子对象;
Composite: 复合对象,包含子组件,通常提供管理子对象的方法,比如 add、remove、get 等方法。


组合模式应用场景

需要表示对象的部分-整体层次结构;

需要客户端统一处理访问单个对象和组合对象;

需要对组合对象结构进行增加或者删除等操作时;


组合模式java举例

以上的概念也许难以理解组合模式,以下举一个java例子说明组合模式

首先,需要定义一个抽象的菜单组件类Component,它是抽象类或者接口,定义了菜单和子菜单的通用接口:
public abstract class Component {
    private String name;

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

    public String getName() {
        return name;
    }

    public abstract void show(); // 显示菜单项

    public abstract void add(Component component); // 添加子菜单或菜单项

    public abstract void remove(Component component); // 删除子菜单或菜单项

    public abstract Component getChild(int index); // 获取子菜单或菜单项
}
菜单或子菜单被定义为Composite,如下:

public class Menu extends Component {
 private List<Component> menuList = new ArrayList<Component>();
    public Menu(String name) {
        super(name);
    }

    public void show() {
        System.out.println("显示菜单项 " + getName());
    }

    public void add(Component component) {
        System.out.println("不支持此操作");
    }

    public void remove(Component component) {
        System.out.println("不支持此操作");
    }

    public Component getChild(int index) {
        System.out.println("不支持此操作");
        return null;
    }
}
而菜单项被定义为Leaf,如下:
public class MenuItem extends Component {
    public MenuItem(String name) {
        super(name);
    }

    public void show() {
        System.out.println("显示菜单项 " + getName());
    }

    public void add(Component component) {
        System.out.println("不支持此操作");
    }

    public void remove(Component component) {
        System.out.println("不支持此操作");
    }

    public Component getChild(int index) {
        System.out.println("不支持此操作");
        return null;
    }
}
最后,我们可以通过如下代码来使用这些组件:

// 创建一个叶子菜单项
Component m1 = new MenuItem("菜单项1");

// 创建一个子菜单
Component m2 = new Menu("子菜单1");

// 给子菜单添加菜单项
Component m3 = new MenuItem("叶子菜单项1");
Component m4 = new MenuItem("叶子菜单项2");
((Menu) m2).add(m3);
((Menu) m2).add(m4);

// 创建一个顶级菜单
Component m5 = new Menu("顶级菜单1");

// 给顶级菜单添加子菜单和菜单项
((Menu) m5).add(m1);
((Menu) m5).add(m2);

// 显示菜单
m5.show();

该菜单系统使用了组合模式来实现,所有菜单项和子菜单都继承自抽象类Component,在使用时可以方便地进行扩展和组合。同时,使用组合模式还可以简化客户端的代码,客户端无需关心菜单项和子菜单的具体类型,只需通过统一的Component接口来访问它们即可。


UML类图如下:
组合模式

组合模式的优缺点

组合模式的优点包括:
可以一致的处理单个对象和组合对象,无需关心具体的对象类型;
增加或删除组成部分非常容易,无需改变其它部分的代码;
组合模式为递归结构,非常符合自然界的组织方式。

组合模式的缺点包括:
在有些情况下,需要限制组合对象中的子组件,这时候 Composite 类的接口中需要添加一些额外的管理子对象的方法,会增加系统的复杂度;
组合模式的设计比较巧妙,但是可能会导致系统设计过于抽象化,使得程序难以读取和调试。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代号diitich

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值