系列文章目录
创建型模式 - 单例模式(一)
创建型模式 - 工厂模式(二)
创建型模式 - 原型模式(三)
创建型模式 - 建造者模式(四)
结构型模式 - 适配器模式(一)
结构型模式 - 桥接模式(二)
结构型模式 - 装饰器模式(三)
结构型模式 - 组合模式(四)
结构型模式 - 外观模式(五)
结构型模式 - 享元模式(六)
结构型模式 - 代理模式(七)
行为型模式 - 模板方法模式(一)
行为型模式 - 命令模式(二)
行为型模式 - 访问者模式(三)
行为型模式 - 迭代器模式(四)
行为型模式 - 观察者模式(五)
行为型模式 - 中介者模式(六)
行为型模式 - 备忘录模式(七)
行为型模式 - 解释器模式(八)
行为型模式 - 状态模式(九)
行为型模式 - 策略模式(十)
行为型模式 - 责任链模式(十一)
前言
一、组合模式
1.1 组合模式介绍
- 组合(Composite)模式:
又叫整体-部分(Part-Whole)模式,它是一种讲对象组合成树状的层次结构的模式,用来表示
“整体-部分”
的关系;
- 组合模式依据树形结构来组合对象,用来表示部分以及整体层次;
- 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:
组合能让客户以一致的方式处理个别对象以及组合对象
;
1.2 组合模式结构
- 抽象构件(Component)角色:
- 主要作用是为树叶构件(Leaf)和树枝(Composite)声明公共接口,在适当情况下,实现所有类共有的接口默认行为,
用于访问和管理Component 子部件
,可以是抽象类或接口;
- 树叶构件(Leaf)角色:
- 是组合中的叶节点对象,他
没有子节点
,用于继承或实现抽象构件;
- 树枝构件(Composite)角色/中间构件:
- 是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件,它只要作用就是
存储和管理子部件,通常包含添加、删除、获取子节点等方法
;
二、实现
例子:
- 实现一个树状图;
2.1 组合模式实现
package com.dozezz.designpattern.composite.composite;
/**
* @Description:
* @Author: dozezz
* @Date: 2021/7/19 20:25
* @Version: 1.0
*/
public abstract class Component {
private String name;
private String desc;
public Component() {
}
public Component(String name, String desc) {
this.name = name;
this.desc = desc;
}
// 为啥不写成抽象的,因为子类未必都需要这方法,如果设计成抽象,每个子类都必须实现它;
// protected abstract void add();
protected void add(Component component) {
throw new UnsupportedOperationException();
}
protected void remove(Component component) {
throw new UnsupportedOperationException();
}
// 这方法子类都需要实现(例子)
protected abstract void print();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Component{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
package com.dozezz.designpattern.composite.composite;
import java.util.ArrayList;
import java.util.List;
/**
* @Description:
* @Author: dozezz
* @Date: 2021/7/19 20:35
* @Version: 1.0
*/
public class CompositeNode extends Component{
List<Component> components = new ArrayList<>();
public CompositeNode() {
}
public CompositeNode(String name, String desc) {
super(name, desc);
}
@Override
protected void add(Component component) {
components.add(component);
}
@Override
protected void remove(Component component) {
components.remove(component);
}
@Override
protected void print() {
System.out.println(getName());
}
}
package com.dozezz.designpattern.composite.composite;
/**
* @Description: 叶子结点
* @Author: dozezz
* @Date: 2021/7/19 20:34
* @Version: 1.0
*/
public class LeafNode extends Component{
public LeafNode(String name, String desc) {
super(name, desc);
}
@Override
protected void print() {
System.out.println(getName());
}
}
package com.dozezz.designpattern.composite.composite;
/**
* @Description:测试
* @Author: dozezz
* @Date: 2021/7/19 20:06
* @Version: 1.0
*/
public class ClientTest {
static void tree(Component component,int deepth){
for (int i = 0; i < deepth; i++) {
System.out.print("----");
}
component.print();
if(component instanceof CompositeNode){
for (Component compositeNode: ((CompositeNode)component).components){
tree(compositeNode,deepth + 1);
}
}
}
public static void main(String[] args) {
Component component = new CompositeNode("root", "root");
Component component1 = new CompositeNode("c1", "c1");
Component component2 = new CompositeNode("c2", "c2");
LeafNode leafNode = new LeafNode("c11", "c11");
LeafNode leafNode1 = new LeafNode("c12", "c12");
Component component3 = new CompositeNode("c21", "c21");
LeafNode leafNode2 = new LeafNode("c211", "c211");
LeafNode leafNode3 = new LeafNode("c212", "c212");
component.add(component1);
component.add(component2);
component1.add(leafNode);
component1.add(leafNode1);
component2.add(component3);
component3.add(leafNode2);
component3.add(leafNode3);
tree(component,0);
// root
// ----c1
// --------c11
// --------c12
// ----c2
// --------c21
// ------------c211
// ------------c212
}
}
三、组合模式
3.1 组合模式应用场景
- 在需要表示一个对象整体与部分的层次结构的场合;
- 要求对隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合;
3.2 组合模式优缺点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无需关系自己处理的是单个对象还是组合对象,简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码;
- 设计比较复杂,客户端需要花费更多时间理清类之间的层次关系;
- 不容易限制容器中的组件,不容易用继承的方法来增加构件的功能;
四、参考文献
- http://c.biancheng.net/view/1373.html
- https://www.bilibili.com/video/BV1G4411c7N4?p=54&spm_id_from=pageDriver
- https://baiyp.ren/JAVA%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-04%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F.html