23种设计模式之组合模式

23种设计模式之组合模式

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

将对象组合成树形结构以表示“部分与整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

特点

  • 组合模式是一种结构型模式。
  • 组合模式能让客户端以一致的方式处理单独对象和组合对象。

通用类图

在这里插入图片描述

组合模式的主要角色:

  • Component

    根节点

    定义了节点要使用的共有方法和属性,可以是一个抽象类、接口或具体类(例如组织)。

  • Leaf

    叶子节点

    继承Component(例如学院下的系(专业)),其下再也没有其他的分支,也就是遍历的最小单位。

  • Composite

    树枝节点

    继承并组合Component,通过组合树枝节点和叶子节点,形成一个树形结构。

优点

  • 组合模式屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),使得客户端可以忽略层次间的差异,使用一致的行为控制不同层次。
  • 组合模式可以很方便地增加 树枝节点叶子节点 对象,只要找到它的父节点就成,符合开闭原则。

缺点

  • 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系。
  • 组合模式在具体实现上违背了设计模式 接口隔离原则依赖倒置原则。

应用场景

  • 要处理的对象可以生成一棵树形结构,且对树上的节点和叶子节点能进行一致的操作。
  • 维护和展示部分与整体关系的场景,如树形菜单、文件和文件夹管理。

二、组合模式

需求:在一个页面上显示出学校的院系组成(一个学校有多个学院,一个学院有多个系)

Component:

package composite;

public abstract class OrganizationComponent {

	//  组织名称
	private String name;

	//  组织描述
	private String desc;

	public OrganizationComponent() {
	}

	public OrganizationComponent(String name, String desc) {
		this.name = name;
		this.desc = desc;
	}

	//  增加一个叶子节点或树枝节点
	protected void add(OrganizationComponent organizationComponent) {
		//  默认实现,需要子类重写
		throw new UnsupportedOperationException();
	}

	//  删除一个叶子节点或树枝节点
	protected void remove(OrganizationComponent organizationComponent) {
		//  默认实现,需要子类重写
		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;
	}


}

Composite:

package composite;

import java.util.ArrayList;
import java.util.List;

public class UniversityComposite extends OrganizationComponent {

	//  组合容器(组合学院)
	List<OrganizationComponent> colleges = new ArrayList<>();

	public UniversityComposite(String name, String desc) {
		super(name, desc);
	}


	@Override
	protected void add(OrganizationComponent organizationComponent) {
		colleges.add(organizationComponent);
	}

	@Override
	protected void remove(OrganizationComponent organizationComponent) {
		colleges.remove(organizationComponent);
	}

	@Override
	protected void print() {
		System.out.println("================" + super.getName() + "================");
		for (OrganizationComponent college : colleges) {
			college.print();
		}
	}

}

package composite;

import java.util.ArrayList;
import java.util.List;

public class CollegeComposite extends OrganizationComponent {

	//  组合容器(组合系)
	List<OrganizationComponent> departments = new ArrayList<>();

	public CollegeComposite(String name, String desc) {
		super(name, desc);
	}

	@Override
	protected void add(OrganizationComponent organizationComponent) {
		departments.add(organizationComponent);
	}

	@Override
	protected void remove(OrganizationComponent organizationComponent) {
		departments.remove(organizationComponent);
	}

	@Override
	protected void print() {
		System.out.println("================" + super.getName() + "================");
		for (OrganizationComponent department : departments) {
			department.print();
		}
	}

}

Leaf:

package composite;


public class DepartmentLeaf extends OrganizationComponent {

	public DepartmentLeaf(String name, String desc) {
		super(name, desc);
	}

	@Override
	protected void print() {
		System.out.println(super.getName());
	}

}

Client:

package composite;

public class Client {

	public static void main(String[] args) {

		//  创建学校
		OrganizationComponent university = new UniversityComposite("XX大学", "双一流大学");
		//  创建学院
		OrganizationComponent computerCollege = new CollegeComposite("计算机学院", "计算机学院");
		OrganizationComponent infoCollege = new CollegeComposite("信息工程学院", "信息工程学院");
		//  为学校添加学院
		university.add(computerCollege);
		university.add(infoCollege);
		//  为学院添加系(专业)
		computerCollege.add(new DepartmentLeaf("软件工程", "软件工程专业"));
		computerCollege.add(new DepartmentLeaf("网络工程", "网络工程专业"));
		computerCollege.add(new DepartmentLeaf("计算机科学与技术", "计算机科学与技术专业"));

		infoCollege.add(new DepartmentLeaf("通信工程", "通信工程专业"));
		infoCollege.add(new DepartmentLeaf("信息程", "信息工程专业"));

		//  打印学校组织结构图
		university.print();
		//  打印学院组织结构图
		computerCollege.print();
		infoCollege.print();

		/**
		 * 输出结果:
		 * ================XX大学================
		 * ================计算机学院================
		 * 软件工程
		 * 网络工程
		 * 计算机科学与技术
		 * ================信息工程学院================
		 * 通信工程
		 * 信息程
		 * ================计算机学院================
		 * 软件工程
		 * 网络工程
		 * 计算机科学与技术
		 * ================信息工程学院================
		 * 通信工程
		 * 信息程
		 *
		 */


	}
}

三、总结

组合模式可以使客户端对部分与整体的操作具有一致性。只要是树形结构或者体现局部和整体的关系的时候,可以考虑一下组合模式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值