引言
随着现代社会的发展,网购已经成为日常生活之中必不可少的一部分,各大电商平台为了竞争,平台中的商家也想出各种各样的办法促销自己的产品,想出各种对策来提升竞争力,优惠券、生活、套餐、打白条等等的方式,可苦恼了这些码农了,如图所示:
最终的价格是多少了?对于大部分的人来说,可不能一眼能看出个结果,业务复杂度不言而喻,平台和商家又不停地想出各种办法来促销产品,怎么适应这种需求得变化,需要工程师们绞尽脑汁来想完成这“变态”的变化。
分析
第一个原则:开闭原则( 对修改关闭,对扩展开放),找出需求的变化与不变分开。
不变:
商品:颜色、尺寸、版本、还有等等属性我就不一一例出来了。
优惠券:计算规则
活动:活动规则
变化:在这我买一下关子,上面那些都是不变的?哪什么是变化的?变化的部分在于它们之间如何组合,这是它们的变化之处,接下来写的代码只是粗略模仿一下业务,请大家不要咬文嚼字,学得只是思想,不是具体的实现。
定义
装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
类图
被装饰者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
执行过程
执行过程可能对于初学者可能会有点绕,万能debugger,开启debug模式查看一下的它的执行过程,这就不多废话。
总结
装饰者模式有它的缺点,大家对java中的IO会有深刻的印象,太多类,太多装饰者了,这就是装饰者模式的缺点,大家可以仔细思考一下,可以采用接下来要讲的工厂模式或者建造者模式相结合就完美了,谢谢各位大佬的阅读,小弟水平有限,请各位大佬的多多指正及转发,大家的支持是我写水文章最大的动力,后续会出更多设计模式到项目的具体代码,请各位大佬多多关照。
github地址:https://github.com/itekko/design_pattern