Decorator与Composite设计模式联合使用场景及类图设计咨询
复合模式(Composite)与装饰器模式(Decorator)组合使用答疑
一、是否存在同时使用两种模式的场景?
当然存在,最典型的就是GUI组件框架的设计场景:
- Composite模式用来处理组件的树形嵌套关系:基础控件(按钮、输入框、文本块)作为叶子节点,容器类组件(面板、窗口、标签页)作为组合节点,可以嵌套添加任意子组件,对外统一暴露渲染、计算尺寸等公共接口,调用方不用区分当前操作的是单个控件还是容器。
- Decorator模式用来给任意组件动态附加通用能力:比如给组件加边框、加滚动条、加悬浮阴影、加事件拦截逻辑,不需要修改原有组件类的代码,也不用为所有组件分别实现同一份附加功能,只需要套对应的装饰器即可。
举个实际使用的例子:你可以给单个按钮套边框装饰器,也可以给一整个包含多个控件的面板套滚动装饰器,两种场景下调用方都只需要调用统一的render()方法就能得到带附加效果的组件,不需要感知内部的嵌套、装饰逻辑。
二、组合场景的类图设计思路
核心是共享同一个顶层抽象组件,整体结构如下:
- 顶层抽象
Component:定义所有组件的公共方法,比如render()、calculateSize(),是两类模式所有类的共同父类 - Composite模式相关实现:
- 叶子节点类:比如
Button、Input,继承Component,实现自身的业务逻辑 - 组合节点类:比如
Panel、Window,继承Component,内部维护List<Component> children集合,实现子组件的增删查接口,重写公共方法时遍历调用所有子组件的对应方法
- 叶子节点类:比如
- Decorator模式相关实现:
- 抽象装饰器类
ComponentDecorator:继承Component,内部持有一个Component类型的被装饰实例,构造方法传入该实例,公共方法默认直接转发给被装饰实例 - 具体装饰器类:比如
BorderDecorator、ScrollDecorator,继承ComponentDecorator,重写公共方法时,先调用被装饰实例的对应方法,再执行附加逻辑(比如渲染完组件后画边框)
- 抽象装饰器类
三、三类是否都需要继承自Component?
答案是必须都继承,这是两个模式可以无缝组合使用的核心前提:
- 对Composite模式来说:叶子节点和组合节点继承同一个
Component,才能实现「容器和叶子对外透明」的核心特性,调用方不需要区分当前处理的是单个控件还是嵌套容器 - 对Decorator模式来说:装饰器继承
Component,才能实现「装饰后的对象可以完全替换原有组件」的透明装饰特性,不管被装饰的是叶子节点还是组合节点,都可以被当做普通Component使用,甚至可以嵌套多层装饰器 - 只有三类共享同一个父类,才能实现灵活的组合:你可以把装饰后的叶子节点加入组合容器,也可以给整个组合容器套装饰器,所有操作都遵循统一的接口规范,不需要额外的类型判断。
内容的提问来源于stack exchange,提问作者Reshma
相关产品推荐
相关产品推荐

