组合模式简介
组合模式定义
组合模式(Composite Pattern)是一种结构型设计模式,又叫部分整体模式,它将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
组合模式包含以下角色:
- Component(抽象构件):抽象构件可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类公有行为的声明和实现,包括添加(add)、删除(remove)、获取子组件(getChildren)以及实现业务逻辑的方法(operation)。它是一个定义了公共的操作方法,可以用于管理和访问component子部件的抽象对象。
- Leaf(叶子构件):叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点,实现了抽象组件接口或抽象类,但没有子组件。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。叶子节点是树形结构中的最底层对象,通常包含具体的业务逻辑实现。
- Composite(树枝节点构件):枝节点构件在组合结构中表示容器节点对象,枝节点节点包含子节点,其子节点可以是叶子节点,也可以是其它枝节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法,在其业务方法中可以递归调用其子节点对业务方法。并允许客户端以统一的方式处理其子组件。
- Client(客户类):使用组合模式来创建和操作复合对象结构。客户端代码不需要关心对象是叶子节点还是树枝节点,因为所有对象都通过抽象组件接口或抽象类来访问。
组合模式优缺点:
优点:
- 客户端代码可以一致地处理单个对象和组合对象,无需关心它们之间的区别。简化了客户端代码;
- 组合模式可以优化处理递归或分级数据结构,因为它将对象组织成树形结构,使得对对象的处理更加直观和高效。
- 容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点:
- 设计复杂性:组合模式可能使设计变得更加复杂,特别是当类之间的层次关系变得复杂时。客户端需要花更多时间来理解这些关系,从而正确地使用组合模式。
- 限制容器中的构件:在组合模式中,当需要添加新的容器构件或叶子构件时,可能很难对容器中的构件类型进行限制。这可能导致设计上的混乱和不必要的复杂性。
- 继承方法的限制:组合模式通常使用继承来实现,但这可能会限制新的构件只能通过继承来添加新功能。这可能限制了系统的灵活性和可扩展性。
- 依赖倒置原则的违反:在某些实现中,组合模式的叶子和树枝的声明可能是实现类而不是接口,这违反了依赖倒置原则。这可能导致代码之间的耦合度过高,不利于维护和扩展。
使用场景
- 表示对象的部分和整体层次结构:当需要表示一个对象的部分以及整体层次结构时,组合模式是一个很好的选择。例如,在文件系统中,根目录下有若干文件和目录,在二级目录下还有目录和文件,这种情况下适合使用组合模式。
- 忽略组合对象与单个对象的差异:如果客户端需要忽略组合对象与单个对象的差异,以一致的方式处理它们,那么可以使用组合模式。这样,客户端代码可以简化,因为无需关心处理的是单个对象还是组合对象。
- 处理递归或分级数据结构:组合模式可以优化处理递归或分级数据结构。通过将对象组织成树形结构,组合模式使得对这些对象的处理更加直观和高效。
通俗来讲就是:
比如在现实生活中,存在很多“部分-整体”的关系。汽车与轮胎、发动机的关系。警察局与科室、警察的关系。学校与学院、学生、老师的关系。
组合模式是一种非常普遍和常用的模式,接口服务互相组合,提供更丰富的接口,实现复杂的业务逻辑。一般情况会选择使用组合代替继承,组合更灵活、更方便。
以下举一个组合模式的例子:
假设学校中有校长管理老师,老师学生,通过以下实例演示学校中人员的层次结构:
创建抽象类,组件Persion 【Component(组件)】
import java.util.List;
/**
* Component(组件)
*
* 为组合中的对象声明接口
* 声明一个接口用于访问和管理Component的子组件
*/
public abstract class Persion {
private String name;
protected List<Persion> persionList;
public abstract void add(Persion persion);
public abstract void delete(Persion persion);
public void input() {
System.out.println(String.format("name is %s", name));
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Persion> getPersionList() {
return persionList;
}
}
创建具体类Principal【Composite(树枝节点构件)】
import java.util.ArrayList;
/**
* Composite(树枝节点构件)
*
* 实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法
* 存储子部件
*
*/
public class Principal extends Persion {
public Principal(String name) {
setName(name);
persionList = new ArrayList<Persion>();
}
@Override
public void add(Persion persion) {
persionList.add(persion);
}
@Override
public void delete(Persion persion) {
persionList.remove(persion);
}
}
创建具体类Teacher【Composite(树枝节点构件)】
import java.util.ArrayList;
/**
* Composite(树枝节点构件)
*
* 实现了在抽象构件中定义行为,包括那些访问及管理子构件对方法
* 存储子部件
*
*/
public class Teacher extends Persion {
public Teacher(String name) {
setName(name);
persionList = new ArrayList<Persion>();
}
@Override
public void add(Persion persion) {
persionList.add(persion);
}
@Override
public void delete(Persion persion) {
persionList.remove(persion);
}
}
创建具体类Student【Leaf(叶子构件)】
/**
* Leaf(叶子构件)
*
* 叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点
* 对于那些访问及管理子构件的方法,可以通过异常等方式进行处理
*/
public class Student extends Persion{
public Student(String name) {
setName(name);
persionList = null;
}
@Override
public void add(Persion persion) {
}
@Override
public void delete(Persion persion) {
}
}
创建测试类【Client(客户类)】
/**
* Client(客户类)
* 使用组合模式来创建和操作复合对象结构
*
*/
public class Client {
public static void main(String[] args) {
Persion principal = new Principal("校长");
Persion teacher1 = new Teacher("教师1");
Persion teacher2 = new Teacher("教师2");
Persion student1 = new Student("学生1");
Persion student2 = new Student("学生2");
Persion student3 = new Student("学生3");
Persion student4 = new Student("学生4");
principal.add(teacher1);
principal.add(teacher2);
teacher1.add(student1);
teacher1.add(student2);
teacher2.add(student3);
teacher2.add(student4);
info("无需", principal);
}
public static void info(String pre ,Persion persion){
System.out.println(String.format("%s管理:%s", pre, persion.getName()));
if(null == persion.getPersionList()){
return;
}
for(Persion persion1 : persion.getPersionList()){
info(persion.getName(), persion1);
}
}
}
输出结果如下所示:
无需管理:校长
校长管理:教师1
教师1管理:学生1
教师1管理:学生2
校长管理:教师2
教师2管理:学生3
教师2管理:学生4
从结果可以看成功根据需求,获取到了校长管理老师,老师管理学生的层级结构。
总而言之:
组合模式,它是一种非常强大的结构型设计模式,用于创建复杂的对象结构,允许用户以统一的方式处理单个对象和复合对象。通过组合模式,你可以构建出具有层次结构的对象模型,这些对象可以像单个对象一样被简单、一致地使用。
组合模式提供一个结构,可同时包容个别对象和组合对象;允许客户对个别对象以及组合对象一视同仁;组合结构内的任意对象称为组件;组件可以是组合,也可以是叶节点;在使用组合模式时,要多加考虑方式,有的时候可以与迭代器模式配合使用。
以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git