Java设计模式-组合模式

文章目录

  • 一、简介
    • 1.1 引入
    • 1.2 定义
  • 二、模式原理
    • 2.1 模式组成
    • 2.2 UML类图
  • 三、实例
    • 3.1 实例概况
    • 3.2 步骤
    • 3.3 UML类图
  • 四、优缺点
    • 4.1 优点
    • 4.2 缺点
  • 五、应用场景

一、简介

1.1 引入

在现实生活中,存在很多"部分-整体"的关系,他们通常都可以用树形结构来表示。比如:大学中的学院与系、军队中的军士结构、公司中的部门分级情况还有文件系统中的文件与文件夹。我们可以将系统中的一个文件夹看成一个容器对象,它包含了多个文件和文件夹,子文件夹中又可以包含多个文件和文件夹。
Java设计模式-组合模式_第1张图片
而文件夹(容器对象)和文件(叶子对象)在功能上有所区别,这使得我们在使用的过程中需要区分容器对象和叶子对象,但大多数情况下,我们希望能在使用的过程中不需要区分二者,而是能够对叶子对象和容器对象的进行一致性使用。

1.2 定义

组合(Composite Pattern)模式的定义:组合模式又叫作整体-部分模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对叶子对象组合对象(容器对象)的使用具有一致性

  • 叶子对象和组合对象实现相同的接口,从而能够将叶子节点和容器节点进行一致性处理
  • 在软件开发中存在大量的树形结构,因此组合模式是一种使用频率较高的结构型设计模式
    Java设计模式-组合模式_第2张图片

二、模式原理

2.1 模式组成

组成(角色) 作用
Component(抽象构件) 它可以是接口抽象类,是叶子节点和容器节点的共同父类。包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。
Leaf(叶子构件) 表示叶子节点对象叶子节点没有子节点,因此叶子节点在实现抽象构件中有关操作子节点的方法时,比如add(),remove()等方法时,可以让方法抛出异常,也可以实现为空操作
Composite(容器构件) 表示容器节点对象容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它的主要作用是存储和管理子构件,通常包含 Add()、Remove()、GetChild() 等方法

子构件表示的就是子节点,所以子构件包括叶子节点和容器节点

2.2 UML类图

Java设计模式-组合模式_第3张图片

三、实例

3.1 实例概况

  • 概述:现有一个学校院系结构为:学校-学院-专业。具体学院与专业如下图所示
    Java设计模式-组合模式_第4张图片
  • 目的:利用组合模式在一个页面中展示出该学校的学院及专业信息

3.2 步骤

  • 步骤一:创建抽象构件(这里是一个抽象类),定义对象的name和des,是叶子构件和容器构件的共同父类
//抽象构件,是叶子构件和容器构件的共同接口
public abstract class Component {
     

	// name是名称,des是描述
	public String name;
	public String des;

	public Component(String name, String des) {
     
		setName(name);
		setDes(des);
	}

	// 抽象方法,叶子节点和容器节点都需要实现
	public abstract void show();

	public void add(Component component) {
     
		throw new UnsupportedOperationException();
	}

	public void remove(Component component) {
     
		throw new UnsupportedOperationException();
	}

	public String getName() {
     
		return name;
	}

	public void setName(String name) {
     
		this.name = name;
	}

	public String getDes() {
     
		return des;
	}

	public void setDes(String des) {
     
		this.des = des;
	}
}
  • 步骤二创建不同的容器构件,并重写父类的add,remove方法和抽象方法show()
// 导包
import java.util.ArrayList;
import java.util.List;

// 容器构件1:University
public class University extends Component {
     
	
	// List用来装College
	// Component引用的是College实例
	List<Component> children = new ArrayList<Component>();

	public University(String name, String des) {
     
		super(name, des);
	}

	// 重写父类add方法,添加College实例
	public void add(Component component) {
     
		children.add(component);
	}
	// 重写父类remove方法,删除College实例
	public void remove(Component component) {
     
		children.remove(component);
	}

	// 打印List中的所有元素,会逐级调用show()方法
	// University调用College中的show()方法,College又调用Major中的show()方法
	public void show() {
     
		System.out.println("--"+getName()+"--");
		for(Component e:children){
     
			e.show();
		}
	}
}
import java.util.ArrayList;
import java.util.List;

// 容器构件1:College
public class College extends Component {
     
	// List用来装Major
	// Component引用的是Major实例
	List<Component> children = new ArrayList<Component>();

	public College(String name, String des) {
     
		super(name, des);
	}
	
	// 重写父类add方法,添加Major实例
	public void add(Component component) {
     
		children.add(component);
	}
	// 重写父类add方法,删除Major实例
	public void remove(Component component) {
     
		children.remove(component);
	}

	// 打印List中的所有元素,会逐级调用show()方法
	// 先通过调用自身getName()方法打印自己的name,然后在增强for中调用的是Major中的show()方法
	public void show() {
     
		System.out.println("--" + getName() + "--");
		for (Component e : children) {
     
			e.show();
		}
	}
}
  • 步骤三:创建叶子节点,只需要重写父类的抽象方法show()即可
//叶子构件:没有子节点,只需要重写父类的抽象方法show()
public class Major extends Component{
     

	public Major(String name,String des){
     
		super(name,des);
	}
	
	//父类的抽象方法,需要重写
	public void show() {
     
		System.out.println(getName());
	}
}
  • 步骤四:创建迦骊惇大学,并生成3个学院及其专业,打印输出结果
public class Client {
     
	public static void main(String[] args) {
     
		Component university = new University("迦骊惇大学", "一流名校");

		// 创建金融学院,会计学院,工程学院
		Component finance = new College("金融学院", "一流专业");
		Component accounting = new College("会计学院", "一流专业");
		Component engineering = new College("工程学院", "一流专业");

		// 为金融学院添加:投资,金融专业
		finance.add(new Major("投资学", "一级学科"));
		finance.add(new Major("金融学", "一级学科"));

		// 为会计学院添加:会计,财务专业
		accounting.add(new Major("会计学", "一级学科"));
		accounting.add(new Major("财务学", "一级学科"));

		// 为工程学院添加:计科,信管专业
		engineering.add(new Major("计科", "一级学科"));
		engineering.add(new Major("信管", "一级学科"));

		// 将三个学院添加到大学university中
		university.add(finance);
		university.add(accounting);
		university.add(engineering);

		university.show();
	}
}
/*
 * 迦骊惇大学 金融学院 投资 金融 会计学院 会计 财务 工程学院 计科 信管
 */
//执行结果
--迦骊惇大学--
--金融学院--
投资学
金融学
--会计学院--
会计学
财务学
--工程学院--
计科
信管

3.3 UML类图

Java设计模式-组合模式_第5张图片
该UML类图还有另外一个表示
Java设计模式-组合模式_第6张图片

四、优缺点

4.1 优点

  • 组合模式中包含叶子对象和组合对象,形成了树形结构,使得用户可以方便的处理叶子对象和组合对象
  • 叶子对象和组合对象实现了相同的接口,使得客户端代码可以一致地处理叶子对象和组合对象,而无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码
  • 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足"开闭原则"

4.2 缺点

  • 设计较为复杂,客户端需要花更多时间理清类之间的层次关系
  • 不容易限制容器中的构件;
  • 不容易用继承的方法来增加构件的新功能;

五、应用场景

  • 当想表示对象的部分-整体层次结构
  • 要求对用户隐藏个体对象和组合对象的不同,即用户可以用统一的接口处理个体对象和组合对象时

你可能感兴趣的:(Java设计模式,java,设计模式)