【设计模式】第十章:组合模式详解及应用案例

系列文章

【设计模式】七大设计原则
【设计模式】第一章:单例模式
【设计模式】第二章:工厂模式
【设计模式】第三章:建造者模式
【设计模式】第四章:原型模式
【设计模式】第五章:适配器模式
【设计模式】第六章:装饰器模式
【设计模式】第七章:代理模式
【设计模式】第八章:桥接模式
【设计模式】第九章:外观模式 / 门面模式
【设计模式】第十章:组合模式
【设计模式】第十一章:享元模式
【设计模式】第十二章:观察者模式
【设计模式】第十三章:模板方法模式
【设计模式】第十四章:策略模式
【设计模式】第十五章:责任链模式
【设计模式】第十六章:迭代器模式
【设计模式】第十七章:状态模式
【设计模式】第十八章:备忘录模式
【设计模式】第十九章:访问者模式
【设计模式】第二十章:解释器模式
【设计模式】第二十一章:命令模式
【设计模式】第二十二章:中介者模式




一、定义

摘自百度百科: 组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。


二、角色分类

抽象构件(Component)

声明了参与组合对象的共有方法和属性,定义了访问其子构件的方法

叶子构件(Leaf)

其表示叶子节点,叶子节点没有子节点,是遍历的最小单位,它实现了在抽象构件中定义的一些行为,

树枝构件(Composite)

它的作用是组合树枝节点和叶子节点构成一个树枝结构,它提供了一个集合来存储子节点,并且实现了抽象构件中定义的行为,包括访问和管理子构件的方法

客户角色(Client)

调用方法的角色


三、实现方式

UML图

Image.png

具体实现

透明模式

抽象构件(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 是树枝。

使用场景: 部分、整体场景,如树形菜单,文件、文件夹的管理。

注意事项: 定义时为具体类。


五、优缺点

优点

  1. 高层模块调用简单。
  2. 节点自由增加。

缺点

在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。


推荐

关注博客和公众号获取最新文章

Bummon’s BlogBummon’s Home公众号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bummon.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值