结构型-组合模式

组合模式(Composite Pattren)

  • 又叫部分整体模式,它创建了对象的树形结构
  • 组合模式依据树形结构来组合对象,用来表示部分-整体层次。
  • 组合模式使得用户可以使用一致的方法操作单个对象和组合对象。
  • 属于结构型模式。

原理图

在这里插入图片描述
在这里插入图片描述

优点

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关系自己处理的是单个对象还是组合对象。
  2. 更容易在组合体内加入新的对象,客户端不会因为加入新的对象而更改源代码,满足开闭原则。

缺点

  1. 如果树形结构非常深,递归操作可能会导致栈溢出或效率下降。

场景举例

假设开发一个旅游规划系统,该系统需要支持用户创建复杂的旅游行程。行程可以包含多个行程,而每个行程又可以包含多个行程和景点。用户希望能够在系统中创建、查看、删除整个行程,包括其下的所有子行程和景点。

代码实现

抽象根节点

/**
 * 旅行计划
 */
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();
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值