设计模式之轻松理解组合模式(Composite)

问题

在双11大促中,为了提高销量,我决定将华为电脑,手机,耳机等系列商品做成礼盒打包销售,初步暂定了两个礼盒:

1. 华为高级礼盒:华为笔记本 + 机械键盘 + 手机礼盒,手机礼盒:手机 + 耳机 + 手表礼盒, 手表礼盒:手表 + 定制表带
2. 华为基础礼盒:华为笔记本 + 无线鼠标 + 手机礼盒,手机礼盒:手机 + 手表礼盒,手表礼盒:手表

销售员问我这两个礼盒如何定价,我告诉他说,把所有商品的价格加起来,打个九折就行。销售员拿着计算器吭哧吭哧算了半天,告诉我高级礼盒价值¥18000,基础礼盒价值¥12000,我不放心,又让另一个销售员算了一遍,算出来高级礼盒价值¥18500,基础礼盒价值¥12600。我一听这可不行啊,打包算个礼盒的钱,这么容易出错。那我得用个设计模式来实现,保证不能出错啊。这就引出了我们本次的主题——组合模式。

概述

使用组合模式有两个很必要的前提,第一就是核心模型可以应用为树形结构,第二就是树形结构的节点有通用属性。就比如二叉树,分为叶子节点和非叶子节点,有一个共同的属性值;比如文件夹和文件,文件夹可包含文件夹或文件,而其都有一个路径,可用来索引或保存等;再比如说我们这里的礼盒套装,礼盒可包含礼盒,也可以包含物品,并且都有一个共同的属性——价格。

实现

定义父类,设置通用属性—价格:

public abstract class Component {

    protected int price;

    public Component(int price) {
        this.price = price;
    }

    /**
     * 计算价格
     *
     * @return 价格
     */
    abstract int calculate();
}

定义礼盒:

public class Container extends Component {

    private List<Component> componentList = new ArrayList<>();

    public Container(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        for (Component component: componentList) {
            price += component.calculate();
        }
        return price;
    }

    public void add(Component component) {
        componentList.add(component);
    }

    public void remove(Component component) {
        componentList.remove(component);
    }
}

定义商品(为了方便,把商品定义简化):

public class Computer extends Component {

    public Computer(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class HeadSet extends Component{

    public HeadSet(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class Keyboard extends Component {

    public Keyboard(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class MobilePhone extends Component {
    public MobilePhone(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class Mouse extends Component{

    public Mouse(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class Watch extends Component {

    public Watch(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

public class WatchBand extends Component {

    public WatchBand(int price) {
        super(price);
    }

    @Override
    public int calculate() {
        return price;
    }
}

计算礼盒价格:

    public static void main(String[] args) {
        // calculate high container
        //container can be free can be not free
        Container highContainer = new Container(0);
        Computer computer = new Computer(10000);
        Keyboard keyboard = new Keyboard(1500);

        Container mobileContainer = new Container(0);
        MobilePhone mobilePhone = new MobilePhone(6000);
        HeadSet headSet = new HeadSet(1300);

        Container watchContainer = new Container(0);
        Watch watch = new Watch(2000);
        WatchBand watchBand = new WatchBand(300);

        highContainer.add(computer);
        highContainer.add(keyboard);
        highContainer.add(mobileContainer);
        mobileContainer.add(mobilePhone);
        mobileContainer.add(headSet);
        mobileContainer.add(watchContainer);
        watchContainer.add(watch);
        watchContainer.add(watchBand);
        System.out.println("高级礼盒价格: " + highContainer.calculate());

        Container lowContainer = new Container(0);
        lowContainer.add(computer);
        Mouse mouse = new Mouse(800);
        lowContainer.add(mouse);
        Container lowMobileContainer = new Container(0);
        Container lowWatchContainer = new Container(0);
        lowWatchContainer.add(watch);
        lowMobileContainer.add(mobilePhone);
        lowMobileContainer.add(lowWatchContainer);
        lowContainer.add(lowMobileContainer);

        System.out.println("基础礼盒价格: " + lowContainer.calculate());
    }

计算结果:

高级礼盒价格: 21100
基础礼盒价格: 18800

总结

从上述的计算过程中,可以大概理解组合模式的思想以及想解决的问题。其是为了解决组合对象的复杂性,我们将组合对象看做整体,我们把对组合对象的操作简化为对整体的操作,而无需关心内部的操作流程,将调用方和内部对象进行解耦。优点:可自由添加节点:我可以轻易的在礼盒中添加物品或删除物品,调用简单:无论我如何添加或删除物品,都不影响计算总价格。

在实现组合模式的过程中,思考到一个问题,可能也是组合模式的缺点,那就是Component作为抽象类,所有需要计算价格的子类都需继承,而这可能是在系统的后期加入的,那么类似于Computer,MobilePhone等早已有抽象父类,那么对其的改造可能需要在对应抽象父类上再抽象一层Component,由各个抽象父类继承。在调整时会有一些困难,以及难以理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值