订单与组合模式

订单

订单在我们的日常生活中非常常见。有时候一个订单中会包含其他的订单,就像下面这样:
在这里插入图片描述
在order订单中包含了两个子订单和一瓶牛奶,两个子订单又分别有自己的内容。这样就形成了一个订单树,具体的商品是叶子节点,订单是非叶子节点。就像下面这样:
在这里插入图片描述
那么我们应该怎么处理这种树形结构呢?答案就是使用组合模式

组合模式

组合模式是一种结构型设计模式,你可以使用它将对象组合成树状结构,并且能够像使用独立对象一样使用它们,所以组合模式又叫“部分整体模式”。

代码

接下来我们用代码来感受一下组合模式。

定义顶层接口

首先,我们先定义最顶层的接口。我把它成为“CalculateAble”,意思是可以被计算价值的东西。在后面的代码中,任何东西都是可以被计算价值的。

/**
 * @author skyline
 */
public interface CalculateAble {
    /**
     * 计算价格
     */
    double calculate();

    /**
     * 当前商品名
     * @return
     */
    String name();

    /**
     * 添加另一个可计算的节点
     * @param calculateAble
     */
    default void add(CalculateAble calculateAble) {}

    /**
     * 获得商品列表
     * @return
     */
    default List<CalculateAble> getCalculateAbleList() {
        return null;
    }
}

一些具体的商品

接下来我们定义一些具体的商品,这些商品是树形的叶子节点

苹果

public class Apple implements CalculateAble {

    @Override
    public double calculate() {
        return 20;
    }

    @Override
    public String name() {
        return "apple";
    }
}

笔记本

public class AlienWareNoteBook implements CalculateAble {
    @Override
    public double calculate() {
        return 25000;
    }

    @Override
    public String name() {
        return "alienWareNoteBook";
    }
}

牛奶

public class Milk implements CalculateAble {
    @Override
    public double calculate() {
        return 25;
    }

    @Override
    public String name() {
        return "Milk";
    }
}

茶叶

public class Tea implements CalculateAble {
    @Override
    public double calculate() {
        return 99;
    }

    @Override
    public String name() {
        return "tea";
    }
}

订单

一个订单中会有多个产品,所以订单对象是树形的非叶子节点

public class Order implements CalculateAble {

    private final List<CalculateAble> calculateAbles;
    private final String name;

    public Order(String name) {
        this.calculateAbles = new ArrayList<>();
        this.name = name;
    }

    @Override
    public double calculate() {
    	//订单的总价格等订单内包含的所有物品的价格之和
        double sum = 0;
        for (CalculateAble calculateAble : calculateAbles) {
            sum += calculateAble.calculate();
        }
        return sum;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public void add(CalculateAble calculateAble) {
        calculateAbles.add(calculateAble);
    }

    @Override
    public List<CalculateAble> getCalculateAbleList() {
        return calculateAbles;
    }
}

main

最后,我们看下main方法

public class CompositeMain {
    public static void main(String[] args) {
	    //创建一个叫order的订单
        CalculateAble order = new Order("order");
        //创建一个叫smallOrder的订单
        CalculateAble smallOrder = new Order("smallOrder");
        //为smallOrder中添加一个商品:苹果
        smallOrder.add(new Apple());
        //为smallOrder中添加一个商品:茶叶
        smallOrder.add(new Tea());
        //创建一个叫bigOrder的订单
        CalculateAble bigOrder = new Order("bigOrder");
        //为bigOrder中添加一个商品:笔记本
        bigOrder.add(new AlienWareNoteBook());
        //将smallOrder添加到order中
        order.add(smallOrder);
        //将bigOrder添加到order中
        order.add(bigOrder);
        //将牛奶添加到order中
        order.add(new Milk());
        //递归打印树形
        loop(order, 0);
        //计算总价
        double calculate = order.calculate();
        System.out.println("总价为:" + calculate);
    }

    private static void loop(CalculateAble calculateAble, int level) {
        if (level == 0) {

        } else if (level == 1) {
            System.out.print("├─");
        } else {
            for (int i = 0; i < level - 1; i++) {
                System.out.print("│ ");
            }
            System.out.print("├─");
        }
        System.out.println(calculateAble.name());
        List<CalculateAble> calculateAbleList = calculateAble.getCalculateAbleList();
        if (calculateAbleList != null) {
            for (CalculateAble able : calculateAbleList) {
                loop(able, level + 1);
            }
        }
    }
}

最后,我们看看执行结果:
在这里插入图片描述
从结果中看到,程序打印出的树形与我们在一开始画的树形是一样的。总价的计算也没有问题。

总结

  1. 如果你要处理树形结构的数据,那你可以考虑组合模式
  2. 如果你希望可以以相同的方式处理简单对象AppleTeaAlienWareNoteBookMilk与复杂对象Order)也可以使用组合模式
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值