设计模式-组合模式(Component)

本文详细介绍了设计模式中的组合模式,包括其定义、结构和类图。通过公司管理系统的案例,展示了如何使用组合模式实现部分-整体的层次结构。同时,讨论了组合模式的优点和缺点,例如一致性使用和增加新构件的挑战。文章还提到了JDK源码中组合模式的应用,如List、Map、Set的addAll方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组合模式

定义

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

结构

Component(抽象构件):为叶子构件和组合构件声明统一的接口,它可以是抽象类也可以是接口。

Leaf(叶子构件):它在组合结构中表示叶子节点对象,它没有子节点,所以对于操作子节点的接口方法通过抛出异常来说明。

Composite(容器构件):它是组合结构中的容器节点对象,它的子节点可以使叶子节点对象,也可以是容器节点对象,它提供了一个list集合用于存放子节点。

类图

Component:

abstract class Component {
	protected String name;
	public abstract void add(Component c);
	public abstract void remove(Component c);
	public abstract Component getChild(int i);
	public abstract void display();
}

Leaf:

public class Leaf extends Component{

	public Leaf(String name){
		this.name = name;
	}
	
	@Override
	public void add(Component c) {
		System.err.println("can not add");
	}

	@Override
	public void remove(Component c) {
		System.err.println("can not remove");
	}

	@Override
	public Component getChild(int i) {
		System.err.println("can not getChild");
		return null;
	}

	@Override
	public void display() {
		System.out.println(name);
	}

}

 

Composite:

public class Composite extends Component{

	ArrayList<Component> children = new ArrayList<Component>();
	
	public Composite(String name){
		this.name = name; 
	}
	
	@Override
	public void add(Component c) {
		children.add(c);
	}

	@Override
	public void remove(Component c) {
		children.remove(c);
	}

	@Override
	public Component getChild(int i) {
		return children.get(i);
	}

	@Override
	public void display() {
		for (Component c : children) {
			System.out.println(c.name);
		}
	}

}

测试类:


	public static void main(String[] args) {
		Component composite = new Composite("容器节点A");
		composite.add(new Composite("容器节点AX"));
		composite.add(new Composite("容器节点AY"));
		composite.display();
		
		Leaf leaf = new Leaf("叶子节点B");
		leaf.display();
	}
	

测试结果:

 

案例

我将以公司管理系统作为案例,我们都知道一个公司做大做强后,必然需要在各个城市建立分公司来开拓市场,那么总公司的办公管理系统需要能复用到分公司,也就是说总公司调用管理功能的方法和分公司调用管理功能的方法最好是一致的。

Company:

public abstract class Company {
	protected String name;
	public abstract void add(Company c);
	public abstract void remove(Company c);
	public abstract void display(int length);
	public abstract void operate();
}

具体分公司(ConcreteCompany):

public class ConcreteCompany extends Company{

	ArrayList<Company> list = new ArrayList<Company>();
	
	public ConcreteCompany(String name){
		this.name = name;
	}
	
	@Override
	public void add(Company c) {
		list.add(c);
	}

	@Override
	public void remove(Company c) {
		list.remove(c);
	}

	@Override
	public void display(int length) {
		for (int i = 0; i < length; i++) {
			System.out.print("-");
		}
		System.out.println(this.name);
		for (Company c : list) {
			c.display(length+2);
		}
	}

	@Override
	public void operate() {
		for (Company c : list) {
			c.operate();
		}
	}

}

人力资源管理部门:

public class HumanResource extends Company{

	public HumanResource(String name){
		this.name = name;
	}
	
	@Override
	public void add(Company c) {
		System.err.println("can not add");
	}

	@Override
	public void remove(Company c) {
		System.err.println("can not remove");
	}

	@Override
	public void display(int length) {
		for (int i = 0; i < length; i++) {
			System.out.print("-");
		}
		System.out.println(this.name);
	}

	@Override
	public void operate() {
		System.out.println(this.name+":人力资源管理");
	}

}

财务部门:

public class FinancialManagement extends Company{

	public FinancialManagement(String name){
		this.name = name;
	}
	
	@Override
	public void add(Company c) {
		System.err.println("can not add");
	}

	@Override
	public void remove(Company c) {
		System.err.println("can not remove");
	}

	@Override
	public void display(int length) {
		for (int i = 0; i < length; i++) {
			System.out.print("-");
		}
		System.out.println(this.name);
	}

	@Override
	public void operate() {
		System.out.println(this.name+":财务管理");
	}

}

测试类:

	public static void main(String[] args) {
		ConcreteCompany company = new ConcreteCompany("北京总公司");
		
		ConcreteCompany company1 = new ConcreteCompany("上海华东分公司");
		HumanResource humanResource = new HumanResource("总公司人力资源部");
		FinancialManagement humanResource1 = new FinancialManagement("总公司财务部");
		company.add(humanResource);
		company.add(humanResource1);
		company.add(company1);
		
		HumanResource humanResource2 = new HumanResource("华东分公司人力资源部");
		FinancialManagement humanResource3 = new FinancialManagement("华东分公司财务部");
		ConcreteCompany company2 = new ConcreteCompany("南京办事处");
		company1.add(humanResource2);
		company1.add(humanResource3);
		company1.add(company2);
		
		HumanResource humanResource4 = new HumanResource("南京办事处人力资源部");
		FinancialManagement humanResource5 = new FinancialManagement("南京办事处财务部");
		company2.add(humanResource4);
		company2.add(humanResource5);
		System.out.println("公司组织架构:");
		company.display(2);
		System.out.println("部门职责:");
		company.operate();
	}	

测试结果:

优点

客户端可以一致的使用组合节点对象和单个节点对象,无需写判断代码,简化代码。

缺点

在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂

JDK源码中的组合模式

List、Map、Set中addAll方法的参数是它本身的一个集合形式,这体现了整体和部分都适用于同一个接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值