组合模式(三)

125 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

上一篇文章我们介绍的是组合模式的各个组成角色,这篇文章我们将找一个具体的场景来实际分析一下组合模式如何使用。

组合模式的应用举例

首先我们再给出类图:

image.png

我们首先假设一个场景:我们公司现在有很多事业线,其中公司的X 事业线有3 个部门,分别为市场部、技术部、运营部,我们需要完成一个统计人数的功能,运用组合模式的话,最后需要一个树枝角色Composite 类来对这三个部门的人数进行统计,具体流程如下:

首先设计的是一个年级接口,定义了一个getCount方法获得这个年级所属班级的人数,从而达到一个一级一级节点的遍历,班级通过实现统一的接口,调用者对单一对象和组合对象的操作具有一致性。

定义抽象构件角色

我们先定义一个事业线接口,它其实就是一个抽象构件角色,接口中声明一个getCount 方法获得这个事业线中所有部门的人数。通过这个接口的不同实现,可以完成对每个叶子角色进行遍历,最终得到count 的总和。

public interface BusinessLine {
	public int getCount();
}

而这个事业线接口中可以对叶子节点进行一级一级的遍历,得到叶子节点其实就是对应的部门,它们通过实现统一的接口,对应调用者来说,调用者对单一对象和组合对象的操作就具有一致性了。

叶子角色

这里再定义三个部门的类,作为具体的叶子角色:

public class Marketing implements BusinessLine {

	@Override
	public int getCount() {
		return 11;
	}

}
public class Ads implements BusinessLine {

	@Override
	public int getCount() {
		return 12;
	}

}
public class Development implements BusinessLine {

	@Override
	public int getCount() {
		return 13;
	}

}

树枝角色

最后我们需要写一个Composite类,它也需要实现事业线接口,同时实现事业线接口里面声明所有的用来管理子类对象的方法,以达到对事业线BusinessLine 接口的最大化。这样一来,对应客户来说,在接口层次上树叶和分支就没有什么区别。

public class Composite implements BusinessLine {

	private List list = new ArrayList();

	public Composite add(BusinessLine businessLine) {
		list.add(businessLine);
		return this;
	}

	public BusinessLine getChild(int i) {
		return (BusinessLine) list.get(i);
	}

	@Override
	public int getCount() {
		int count = 0;
		for (int i = 0; i < list.size(); i++) {
			BusinessLine businessLine = (BusinessLine) list.get(i);
			count += businessLine.getCount();
		}
		return count;
	}

	public BusinessLine remove(BusinessLine businessLine) {
		list.remove(businessLine);
		return this;
	}

}

在这里有一个小技巧,就是add 和romove 方法返回的是this指针,这样在操作的时候可以反复的中这个方法返回对象,然后就可以继续进行想要的操作。

同时在这里的Composite类和对应的部门的类实现的是统一接口,这样实现了功能的一致性,调用起来会比较方便,如下:

composite.add(new Ads()).add(new Marketing());

客户端调用

通过客户端的调用就可以体现组合模式的实用性所在:

public class Client {

	public static void main(String[] args) {

		Composite businessLine = new Composite();

		Ads ads = new Ads();
		Marketing marketing = new Marketing();
		Developent developent = new Developent();

		businessLine.add(ads).add(marketing);
		System.out.println("the people number of ads and developent" + grade.getCount());

	}
}

总结

至此,我们已完成组合模式的介绍。其最主要的作用就是可以让客户端调用变得非常简单。

使用组合模式会有比使用继承关系更灵活的功能,并且可以灵活地区组合子对象和父对象之间的关系,从而使客户端的调用变得十分简单。

因为组合模式的固有特点,客户端可以一致的使用组合结构或其中单个对象,这样对于客户端来说,它就不需要关系自己目前处理的是单个对象还是整个组合结构,也减少了很多客户端代码。