组合模式(Composite Pattren)
- 又叫部分整体模式,它创建了对象的树形结构
- 组合模式依据树形结构来组合对象,用来表示部分-整体层次。
- 组合模式使得用户可以使用一致的方法操作单个对象和组合对象。
- 属于结构型模式。
原理图
优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关系自己处理的是单个对象还是组合对象。
- 更容易在组合体内加入新的对象,客户端不会因为加入新的对象而更改源代码,满足开闭原则。
缺点
- 如果树形结构非常深,递归操作可能会导致栈溢出或效率下降。
场景举例
假设开发一个旅游规划系统,该系统需要支持用户创建复杂的旅游行程。行程可以包含多个行程,而每个行程又可以包含多个行程和景点。用户希望能够在系统中创建、查看、删除整个行程,包括其下的所有子行程和景点。
代码实现
抽象根节点
/**
* 旅行计划
*/
public interface TravelPlan {
default List<TravelPlan> getChildJourney(){
return null;
};
/**
* 查看旅行计划
*/
void viewPlan();
/**
* 添加计划
* @param travelPlan
*/
void addPlan(TravelPlan travelPlan);
/**
* 删除计划
* @param travelPlan
*/
void deletePlan(TravelPlan travelPlan);
/**
* 删除所有子行程
*/
default void deleteAllChildren(){};
}
树枝节点
/**
* 定义行程,一个行程下可以有多个子行程或者景点
*/
public class Journey implements TravelPlan{
/**
* 行程名
*/
private String name;
private int level;
/**
* 子行程
*/
private List<TravelPlan> childJourney;
public Journey(String name,int level) {
this.name = name;
this.level = level;
childJourney = new ArrayList<>();
}
public String getName() {
return name;
}
@Override
public List<TravelPlan> getChildJourney() {
return childJourney;
}
@Override
public void viewPlan() {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println(name);
if (!CollectionUtils.isEmpty(childJourney)) {
for (TravelPlan travelPlan : childJourney) {
travelPlan.viewPlan();
}
}
}
@Override
public void addPlan(TravelPlan travelPlan) {
if (this == travelPlan) {
throw new UnsupportedOperationException("不能自己添加自己");
}
childJourney.add(travelPlan);
}
@Override
public void deletePlan(TravelPlan travelPlan) {
List<TravelPlan> childJourney = travelPlan.getChildJourney();
travelPlan.deleteAllChildren();
this.childJourney.remove(travelPlan);
}
@Override
public void deleteAllChildren() {
this.childJourney = null;
}
}
叶子节点
/**
* 定义景点(叶子节点)
*/
public class ScenicSpot implements TravelPlan{
private String name;
private int level;
public ScenicSpot(String name, int level) {
this.name = name;
this.level = level;
}
@Override
public void viewPlan() {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println("-" + name);
}
@Override
public void addPlan(TravelPlan travelPlan) {
throw new UnsupportedOperationException("景点类型不支持添加操作");
}
@Override
public void deletePlan(TravelPlan travelPlan) {
}
}
结果展示
public class Main {
public static void main(String[] args) {
Journey journey1 = new Journey("行程1", 1);
Journey journeyA = new Journey("行程A", 2);
Journey journeyB = new Journey("行程B", 2);
ScenicSpot wts = new ScenicSpot("五台山", 3);
ScenicSpot pygc = new ScenicSpot("平遥古城", 3);
ScenicSpot ygsk = new ScenicSpot("云冈石窟", 3);
ScenicSpot tt = new ScenicSpot("天坛", 3);
ScenicSpot gg = new ScenicSpot("故宫", 3);
ScenicSpot yhy = new ScenicSpot("颐和园", 3);
journey1.addPlan(journeyA);
journeyA.addPlan(wts);
journeyA.addPlan(pygc);
journeyA.addPlan(ygsk);
System.out.println("*********查看行程************");
journey1.viewPlan();
System.out.println("*********添加行程(行程1下的景点)************");
journey1.addPlan(journeyB);
journeyB.addPlan(tt);
journeyB.addPlan(gg);
journeyB.addPlan(yhy);
journey1.addPlan(new ScenicSpot("行程1下的景点",2));
journey1.viewPlan();
System.out.println("*********删除景点(颐和园)************");
journeyB.deletePlan(yhy);
journey1.viewPlan();
}
}