装饰者模式完成商品结算问题

引言

随着现代社会的发展,网购已经成为日常生活之中必不可少的一部分,各大电商平台为了竞争,平台中的商家也想出各种各样的办法促销自己的产品,想出各种对策来提升竞争力,优惠券、生活、套餐、打白条等等的方式,可苦恼了这些码农了,如图所示:


image.png

最终的价格是多少了?对于大部分的人来说,可不能一眼能看出个结果,业务复杂度不言而喻,平台和商家又不停地想出各种办法来促销产品,怎么适应这种需求得变化,需要工程师们绞尽脑汁来想完成这“变态”的变化。

分析

第一个原则:开闭原则( 对修改关闭,对扩展开放),找出需求的变化与不变分开。
不变:
商品:颜色、尺寸、版本、还有等等属性我就不一一例出来了。
优惠券:计算规则
活动:活动规则
变化:在这我买一下关子,上面那些都是不变的?哪什么是变化的?变化的部分在于它们之间如何组合,这是它们的变化之处,接下来写的代码只是粗略模仿一下业务,请大家不要咬文嚼字,学得只是思想,不是具体的实现。

定义

装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

类图

image.png

被装饰者goodsService

package com.duoduo.decorator;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:21
 */
public interface GoodsService {

    Double cost();
}

被装饰者实现类(GoodsServiceImpl)

package com.duoduo.decorator.impl;

import com.duoduo.decorator.GoodsService;
import org.springframework.stereotype.Service;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:26
 */
@Service
public class GoodsServiceImpl implements GoodsService {


    @Override
    public Double cost() {
        //伪代码 计算出商品价格为18888.9
        return 18888.9;
    }
}

装饰者(优惠券)

package com.duoduo.decorator;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:21
 */
public interface CouponService extends GoodsService{

    Double couponCost();

    void setGoodsService(GoodsService goodsService);

}

装饰者实现类一(优惠券)

package com.duoduo.decorator.impl;

import com.duoduo.decorator.CouponService;
import com.duoduo.decorator.GoodsService;
import org.springframework.stereotype.Service;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:26
 */
@Service
public class CouponServiceImpl implements CouponService {

    private GoodsService goodsService;

    @Override
    public Double couponCost() {
        //伪代码 计算优惠券价格为666.0
        return 666.0;
    }

    @Override
    public Double cost() {
        return goodsService.cost() - couponCost();
    }

    @Override
    public void setGoodsService(GoodsService goodsService) {
        this.goodsService = goodsService;
    }
}

装饰者二(活动)

package com.duoduo.decorator;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:21
 */
public interface ActivtyService extends GoodsService{

    Double activtyCost();

    void setGoodsService(GoodsService goodsService);
}

装饰者二实现类(活动)

package com.duoduo.decorator.impl;

import com.duoduo.decorator.ActivtyService;
import com.duoduo.decorator.GoodsService;
import org.springframework.stereotype.Service;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:26
 */
@Service
public class ActivtyServiceImpl implements ActivtyService {


    private GoodsService goodsService;

    @Override
    public Double activtyCost() {
        //伪代码 计算活动优惠价格为1000.0
        return 1000.0;
    }

    @Override
    public Double cost() {
        return goodsService.cost() - activtyCost();
    }

    @Override
    public void setGoodsService(GoodsService goodsService) {
        this.goodsService = goodsService;
    }
}

测试类

package com.duoduo.decorator;


import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author lixiaolong
 * @create 2019-03-21 11:32
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class DecoratorTest {



    @Autowired
    private CouponService couponService;

    @Qualifier("goodsServiceImpl")
    @Autowired
    private GoodsService goodsService;

    @Autowired
    private ActivtyService activtyService;
    @Test
    public void contextLoads() {

        activtyService.setGoodsService(goodsService);
        couponService.setGoodsService(activtyService);
        Double cost = couponService.cost();
        //18888.9 - 1000 - 666 = 17222.9
        log.info("最终价格为:{}",cost);
    }
}

运行结果

2019-03-21 11:52:48.471  INFO 8736 --- [           main] com.duoduo.decorator.DecoratorTest       : 最终价格为:17222.9

执行过程

image.png

执行过程可能对于初学者可能会有点绕,万能debugger,开启debug模式查看一下的它的执行过程,这就不多废话。

总结

装饰者模式有它的缺点,大家对java中的IO会有深刻的印象,太多类,太多装饰者了,这就是装饰者模式的缺点,大家可以仔细思考一下,可以采用接下来要讲的工厂模式或者建造者模式相结合就完美了,谢谢各位大佬的阅读,小弟水平有限,请各位大佬的多多指正及转发,大家的支持是我写水文章最大的动力,后续会出更多设计模式到项目的具体代码,请各位大佬多多关照。
github地址:https://github.com/itekko/design_pattern

你可能感兴趣的:(装饰者模式完成商品结算问题)