一、定义
定义:将对象组合成树形结构以表示“部分-整体”
组合模式使客户端对单个对象和组合对象保持一致的处理
类型:结构型
二、适用场景
希望客户端可以忽略组合对象与单个对象的差异时
处理一个树形结构时
三、优点
清楚地定义分层次的复杂对象,表示对象的全部或者部分层次
让客户端忽略了层次的差异,方便对整个层次结构进行控制。
简化客户端的代码
符合开闭原则
四、缺点
限制类型时会较为复杂
使设计变得更加抽象
五、Coding(场景课程目录,课程。课程目录里可以有多个课程,或者课程目录有多个目录)
1. 创建CatalogComponent 抽象类
/**
* 目录组件
*/
public abstract class CatalogComponent {
public void add(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持添加操作");
}
public void remove(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持删除操作");
}
public String getName(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持获取名称操作");
}
public double getNPrice(CatalogComponent catalogComponent){
throw new UnsupportedOperationException("不支持获取价格操作");
}
public void print(){
throw new UnsupportedOperationException("不支持打印操作");
}
}
2. 创建Course课程类,继承课程目录。课程类中有name和price属性,以及重写getName方法,getPrice方法,和print方法
public class Course extends CatalogComponent {
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(CatalogComponent catalogComponent) {
return this.name;
}
@Override
public double getNPrice(CatalogComponent catalogComponent) {
return this.price;
}
@Override
public void print() {
System.out.println("课程名称:" + name + " 价格: " + price);
}
}
3. 创建CourseCatalog 类。里面有多个课程目录。level代码目录等级。
/**
* 课程目录
*/
public class CourseCatalog extends CatalogComponent{
private List<CatalogComponent> items = new ArrayList<>();
//目录名称
private String name;
private Integer level;
public CourseCatalog(String name, Integer level) {
this.name = name;
this.level = level;
}
@Override
public String getName(CatalogComponent catalogComponent) {
return this.name;
}
@Override
public void add(CatalogComponent catalogComponent) {
items.add(catalogComponent);
}
@Override
public void remove(CatalogComponent catalogComponent) {
items.remove(catalogComponent);
}
@Override
public void print() {
System.out.println(this.name);
for(CatalogComponent catalogComponent : items){
if(this.level != null){
for(int i = 0; i < this.level ; i++){
System.out.print(" ");
}
}
catalogComponent.print();
}
}
}
4. 测试
public class Test {
public static void main(String[] args) {
CatalogComponent javaScriptCourse = new Course("JavaScript基础",400);
CatalogComponent typeScriptCourse = new Course("TypeScript基础",300);
CatalogComponent javaCourse = new Course("Java基础",200);
CatalogComponent javaCourse2 = new Course("Java设计模式",200);
CatalogComponent javaCourse3 = new Course("Android课程",300);
CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程目录", 2);
javaCourseCatalog.add(javaCourse);
javaCourseCatalog.add(javaCourse2);
javaCourseCatalog.add(javaCourse3);
CatalogComponent mainCourseCatalog = new CourseCatalog("课程主目录", 1);
mainCourseCatalog.add(javaScriptCourse);
mainCourseCatalog.add(typeScriptCourse);
mainCourseCatalog.add(javaCourseCatalog);
mainCourseCatalog.print();
}
}
输出为:

5 UML图

六、在源码中的应用
1.jdk java.awt中的Container类

add方法
public Component add(Component var1) {
this.addImpl(var1, (Object)null, -1);
return var1;
}
2. HashMap
HasMap实现了Map接口,并且putAll测参数为Map
public void putAll(Map<? extends K, ? extends V> var1)
3. Java.util.ArrayList
ArrayList实现List接口,List接口继承自Collection,addAll中参数为Collection
public boolean addAll(Collection<? extends E> var1)
4. Mybatis中SqlNode 接口
public interface SqlNode {
boolean apply(DynamicContext var1);
}
多个SqlNode对象
public class MixedSqlNode implements SqlNode {
private List<SqlNode> contents;
public MixedSqlNode(List<SqlNode> contents) {
this.contents = contents;
}
public boolean apply(DynamicContext context) {
Iterator i$ = this.contents.iterator();
while(i$.hasNext()) {
SqlNode sqlNode = (SqlNode)i$.next();
sqlNode.apply(context);
}
return true;
}
}