系列文章
【设计模式】七大设计原则
【设计模式】第一章:单例模式
【设计模式】第二章:工厂模式
【设计模式】第三章:建造者模式
【设计模式】第四章:原型模式
【设计模式】第五章:适配器模式
【设计模式】第六章:装饰器模式
【设计模式】第七章:代理模式
【设计模式】第八章:桥接模式
【设计模式】第九章:外观模式 / 门面模式
【设计模式】第十章:组合模式
【设计模式】第十一章:享元模式
【设计模式】第十二章:观察者模式
【设计模式】第十三章:模板方法模式
【设计模式】第十四章:策略模式
【设计模式】第十五章:责任链模式
【设计模式】第十六章:迭代器模式
【设计模式】第十七章:状态模式
【设计模式】第十八章:备忘录模式
【设计模式】第十九章:访问者模式
【设计模式】第二十章:解释器模式
【设计模式】第二十一章:命令模式
【设计模式】第二十二章:中介者模式
文章目录
- 系列文章
- 一、定义
- 二、角色分类
- 三、实现方式
- UML图
- 具体实现
- 透明模式
- 安全模式
- 透明模式和安全模式的区别
- 四、应用场景
- 五、优缺点
- 优点
- 缺点
一、定义
摘自百度百科: 组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。
二、角色分类
抽象构件(Component)
声明了参与组合对象的共有方法和属性,定义了访问其子构件的方法
叶子构件(Leaf)
其表示叶子节点,叶子节点没有子节点,是遍历的最小单位,它实现了在抽象构件中定义的一些行为,
树枝构件(Composite)
它的作用是组合树枝节点和叶子节点构成一个树枝结构,它提供了一个集合来存储子节点,并且实现了抽象构件中定义的行为,包括访问和管理子构件的方法
客户角色(Client)
调用方法的角色
三、实现方式
UML图
具体实现
透明模式
抽象构件(Component)
public abstract class Component {
// 个体与整体都有
public void operation() {
// 业务逻辑
}
// 增加一个叶子构件或树枝构件
public abstract void add(Component component);
// 删除一个叶子构件或树枝构件
public abstract void remove(Component component);
// 获取分支下的所有叶子构件和树枝构件
public abstract List<Component> getChildren();
}
树枝构件(Composite)
public class Composite extends Component {
// 构件容器
private List<Component> componentList = new ArrayList<>();
// 增加一个叶子构件或树枝构件
public void add(Component component) {
this.componentList.add(component);
}
// 删除一个叶子构件或树枝构件
public void remove(Component component) {
this.componentList.remove(component);
}
// 获取分支下所有叶子构件和树枝构件
public List<Component> getChildren() {
return this.componentList;
}
}
叶子构件(Leaf)
public class Leaf extends Component {
public void add(Component component) {
// 空实现
}
public void remove(Component component) {
// 空实现
}
public List<Component> getChildren() {
// 空实现
}
}
客户角色(Client)
public class Client {
public static void main(String[] args) {
// 创建一个根节点
Composite root = new Composite();
root.operation();
// 创建一个树枝构件
Composite branch = new Composite();
// 创建一个叶子节点
Leaf leaf = new Leaf();
// 建立整体
root.add(branch);
branch.add(leaf);
}
public static void showTree(Component root) {
root.getChildren.foreach(any->{
if(any instanceof Leaf) {
// 叶子构件
any.operation();
}else {
// 树枝构件
showTree(any);
}
});
}
}
安全模式
抽象构件(Component)
public abstract class Component {
// 个体和整体都有
public void operation() {
// 业务逻辑
}
}
树枝构件(Composite)
public class Composite extends Component {
// 构件容器
private List<Component> componentList = new ArrayList<>();
public void add(Component component){
this.componentArrayList.add(component);
}
// 删除一个叶子构件或树枝构件
public void remove(Component component){
this.componentArrayList.remove(component);
}
// 获取分支下的所有叶子构件和树枝构件
public List<Component> getChildren(){
return this.componentArrayList;
}
}
叶子构件(Leaf)
public class Leaf extends Component {
// 可以覆写父类方法
}
客户角色(Client)
public class Client {
public static void main(String[] args) {
//创建一个根节点
Composite root = new Composite();
root.operation();
//创建一个树枝构件
Composite branch = new Composite();
//创建一个叶子节点
Leaf leaf = new Leaf();
//建立整体
root.add(branch);
branch.add(leaf);
}
//通过递归遍历树
public static void showTree(Composite root){
for(Component c:root.getChildren()){
if(c instanceof Leaf){
// 叶子节点
c.operation();
}else{
// 树枝节点
showTree((Composite)c);
}
}
}
}
透明模式和安全模式的区别
- 安全模式在抽象组件中只定义一些默认的行为或属性,它是把树枝节点和树叶节点彻底分开;透明模式是把用来组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,通过判断确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题,不是很建议的方式。
- 安全模式与依赖倒置原则冲突;透明模式的好处就是它基本遵循了依赖倒转原则,方便系统进行扩展。
- 安全模式在遍历树形结构的的时候需要进行强制类型转换;在透明模式下,遍历整个树形结构是比较容易的,不用进行强制类型转换。
四、应用场景
以下部分内容摘自菜鸟教程
意图: 将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决: 它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决: 树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码: 树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作数也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
使用场景: 部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项: 定义时为具体类。
五、优缺点
优点
- 高层模块调用简单。
- 节点自由增加。
缺点
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。