Java性能调优实战
刘超
金山软件西山居技术经理
立即订阅
7535 人已学习
课程目录
已完结 48 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 怎样才能做好性能调优?
免费
模块一 · 概述 (2讲)
01 | 如何制定性能调优标准?
02 | 如何制定性能调优策略?
模块二 · Java编程性能调优 (10讲)
03 | 字符串性能优化不容小觑,百M内存轻松存储几十G数据
04 | 慎重使用正则表达式
05 | ArrayList还是LinkedList?使用不当性能差千倍
加餐 | 推荐几款常用的性能测试工具
06 | Stream如何提高遍历集合效率?
07 | 深入浅出HashMap的设计与优化
08 | 网络通信优化之I/O模型:如何解决高并发下I/O瓶颈?
09 | 网络通信优化之序列化:避免使用Java序列化
10 | 网络通信优化之通信协议:如何优化RPC网络通信?
11 | 答疑课堂:深入了解NIO的优化实现原理
模块三 · 多线程性能调优 (10讲)
12 | 多线程之锁优化(上):深入了解Synchronized同步锁的优化方法
13 | 多线程之锁优化(中):深入了解Lock同步锁的优化方法
14 | 多线程之锁优化(下):使用乐观锁优化并行操作
15 | 多线程调优(上):哪些操作导致了上下文切换?
16 | 多线程调优(下):如何优化多线程上下文切换?
17 | 并发容器的使用:识别不同场景下最优容器
18 | 如何设置线程池大小?
19 | 如何用协程来优化多线程业务?
20 | 答疑课堂:模块三热点问题解答
加餐 | 什么是数据的强、弱一致性?
模块四 · JVM性能监测及调优 (6讲)
21 | 磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型
22 | 深入JVM即时编译器JIT,优化Java编译
23 | 如何优化垃圾回收机制?
24 | 如何优化JVM内存分配?
25 | 内存持续上升,我该如何排查问题?
26 | 答疑课堂:模块四热点问题解答
模块五 · 设计模式调优 (6讲)
27 | 单例模式:如何创建单一对象优化系统性能?
28 | 原型模式与享元模式:提升系统性能的利器
29 | 如何使用设计模式优化并发编程?
30 | 生产者消费者模式:电商库存设计优化
31 | 装饰器模式:如何优化电商系统中复杂的商品价格策略?
32 | 答疑课堂:模块五思考题集锦
模块六 · 数据库性能调优 (8讲)
33 | MySQL调优之SQL语句:如何写出高性能SQL语句?
34 | MySQL调优之事务:高并发场景下的数据库事务调优
35 | MySQL调优之索引:索引的失效与优化
36 | 记一次线上SQL死锁事故:如何避免死锁?
37 | 什么时候需要分表分库?
38 | 电商系统表设计优化案例分析
39 | 数据库参数设置优化,失之毫厘差之千里
40 | 答疑课堂:MySQL中InnoDB的知识点串讲
模块七 · 实战演练场 (4讲)
41 | 如何设计更优的分布式锁?
42 | 电商系统的分布式事务调优
43 | 如何使用缓存优化系统性能?
44 | 记一次双十一抢购性能瓶颈调优
结束语 (1讲)
结束语 | 栉风沐雨,砥砺前行!
Java性能调优实战
登录|注册

31 | 装饰器模式:如何优化电商系统中复杂的商品价格策略?

刘超 2019-08-01
你好,我是刘超。
开始今天的学习之前,我想先请你思考一个问题。假设现在有这样一个需求,让你设计一个装修功能,用户可以动态选择不同的装修功能来装饰自己的房子。例如,水电装修、天花板以及粉刷墙等属于基本功能,而设计窗帘装饰窗户、设计吊顶装饰房顶等未必是所有用户都需要的,这些功能则需要实现动态添加。还有就是一旦有新的装修功能,我们也可以实现动态添加。如果要你来负责,你会怎么设计呢?
此时你可能会想了,通常给一个对象添加功能,要么直接修改代码,在对象中添加相应的功能,要么派生对应的子类来扩展。然而,前者每次都需要修改对象的代码,这显然不是理想的面向对象设计,即便后者是通过派生对应的子类来扩展,也很难满足复杂的随意组合功能需求。
面对这种情况,使用装饰器模式应该再合适不过了。它的优势我想你多少知道一点,我在这里总结一下。
装饰器模式能够实现为对象动态添加装修功能,它是从一个对象的外部来给对象添加功能,所以有非常灵活的扩展性,我们可以在对原来的代码毫无修改的前提下,为对象添加新功能。除此之外,装饰器模式还能够实现对象的动态组合,借此我们可以很灵活地给动态组合的对象,匹配所需要的功能。
下面我们就通过实践,具体看看该模式的优势。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java性能调优实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(21)

  • 密码123456
    责任链。最常见到的就是接收http请求了。帮我们转码,转化成实体类,等等。策略模式。最常简单和用到的就是集合排序,自定义排序规则。装饰器,最常见到的就是各种流,比如字符流,字节流等

    作者回复: 👍🏻

    2019-08-01
    15
  • QQ怪
    老师这个案例来的太及时了,正想重构公司订单优惠劵红包扣除这方面的代码,真的是及时雨啊?厉害厉害👍🏻
    2019-08-01
    7
  • nightmare
    netty中的pipeline,tomcat中的filter,属于责任链, springmvc中对参数解析的就是 策略模式,每一个参数类型一个实现类,用for循环解析参数 java. io就是经典的装饰器模式

    作者回复: 有读源码习惯👍🏻

    2019-08-01
    6
  • CCC
    有几个今年秋招的!举个手!老师的课程真的收获很多!
    2019-08-01
    5
  • 疯狂咸鱼
    老师,为什么java io是装饰器模式

    作者回复: 我们知道,InputStream是直接读写文件的,除了InputStream,在其上层还有BufferedInputStream、DataInputStream等其他修饰类,增加了缓存读取、类型读取等功能,相当于InputStream之上加了很多修饰功能,在所以它是一个装饰器模式。

    2019-09-01
    1
  • 感觉老师在红包这个例子里面,其实最重要的解耦是装饰器实现的各种基本的优惠打折手段与工厂的各种优惠规则比如红包抵用券可叠加等等。

    作者回复: 对的,主要用来优化业务的复杂度。

    2019-08-02
    1
  • 冯传博
    希望能有个类图,这样就能一目了然的看清楚各个类之间的关系了

    作者回复: 好的,后续补上

    2019-08-01
    1
  • -W.LI-
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
    BigDecimal payTotalMoney = new BigDecimal(0);
    payTotalMoney = super.countPayMoney(orderDetail);
    payTotalMoney = countCouponPayMoney(orderDetail);
    return payTotalMoney;
    }
    老师好!这里为啥要调用父类的countPayMoney()方法啊?
    责任链模式:感觉责任连模式比较固定不怎么会变一层往一层调用,解耦,某一层变了不影响别的层。
    策略模式:策略模式,虽然也是封装了很多不同的策略,但是使用时一般一次只选一个实现类使用,不会有嵌套。
    装饰者模式:责任链有的优点他都有,装饰者还能动态组合。
    谢谢老师,希望给出详细答案谢谢

    作者回复: 由于我们这里考虑到灵活的组合模式,所以需要调用父类的countPayMoney()方法。

    2019-08-01
    1
  • Geek_f6fba7
    老师,问一个小白问题,产品Map<PromotionType, SupportPromotions> supportPromotions; //支持促销类型 怎么存入数据库了?

    作者回复: 简单的将SupportPromotions促销类型存储起来就好了

    2019-12-04
  • wuyin
    public static BigDecimal getPayMoney(OrderDetail orderDetail) { //获取给商品设定的促销类型 Map supportPromotionslist = orderDetail.getMerchandise().getSupportPromotions(); //初始化计算类 IBaseCount baseCount = new BaseCount(); if(supportPromotionslist!=null && supportPromotionslist.size()>0) { for(PromotionType promotionType: supportPromotionslist.keySet()) {//遍历设置的促销类型,通过装饰器组合促销类型 baseCount = protmotion(supportPromotionslist.get(promotionType), baseCount); } } return baseCount.countPayMoney(orderDetail); }
    baseCount只会有一种优惠类型吧,怎么进行组合计算呢

    作者回复: 这里的场景是多个叠加优惠

    2019-12-03
  • neohope
    老师您好,想请教一下,在实际做优惠活动时,很多活动策略之间是相互排斥的,用了优惠1就不能用优惠2,用了优惠2就不能用红包。这种自动选择最优优惠策略,在哪里实现比较合理呢?多谢!

    作者回复: 也可以基于该模式实现,我们只需要将叠加逻辑改成选择最优逻辑即可。

    2019-11-24
  • 依然亦晨
    老师,有个疑问,促销类型类里看到用了clone方法,原型模式,为什么后边都没用调用clone方法的地方呢?

    作者回复: 对的,没有使用,可以忽略

    2019-09-21
  • 风轻扬
    老师,知行合一同学提的问题。
    BigDecimal payTotalMoney = new BigDecimal(0);
    payTotalMoney = super.countPayMoney(orderDetail);
    payTotalMoney = countCouponPayMoney(orderDetail);
    payTotalMoney不就被覆盖了吗?
    这里的super.countPayMoney()是不能去掉的。去掉就报空指针
    RedPacketDecorator中的super代表的是BaseCount,super.countPayMoney()承担着计算总额的任务。
    CouponDecorator中的super代表的是RedPacketDecorator,这里的super.countPayMoney()承担着计算计算红包优惠额的任务。
    两个super.countPayMoney都不可以省略的。
    望老师明示

    作者回复: super.countPayMoney(orderDetail)主要是计算了orderDetail中的paymoney,这里写的可读性不是很好,可以这样理解:

    BigDecimal payTotalMoney = new BigDecimal(0);
    super.countPayMoney(orderDetail);//计算paymoney;
    payTotalMoney = countCouponPayMoney(orderDetail);//计算优惠后的价格;

    2019-09-18
  • 风轻扬
    老师,装修功能里面的BaseDecorator为什么要用abstract修饰呢?也没有抽象方法呢

    作者回复: 这是一个抽象基类,没有特别的,方便后面扩展

    2019-09-16
  • godtrue
    😀老师,装饰器模式的性能优化点在哪里?是不是加速了研发调整代码扩展代码的速度!

    作者回复: 代码易扩展,逻辑清晰

    2019-09-13
  • 飞鸽
    促销、红包这种情况复杂多变。基于规则配置处理更好。
    2019-09-06
  • 疯狂咸鱼
    老师你讲的太好了,要加餐加餐
    2019-09-01
  • Gred
    老师您这段优化的装饰器模式代码里面,就用到装饰器、责任链以及工厂模式。不愧是老师,厉害厉害。
    2019-08-14
  • Gred
    老师,您在SupportPromotions重写 clone 方法,只对类进行拷贝,但是成员变量只是浅拷贝,如果要实际应用业务场景,是不是应该改用深拷贝,避免其他订单的优化券等信息影响到了。
    2019-08-13
  • 知行合一
    BigDecimal payTotalMoney = new BigDecimal(0);
    payTotalMoney = super.countPayMoney(orderDetail);
    payTotalMoney = countCouponPayMoney(orderDetail);
    payTotalMoney不就被覆盖了吗?

    作者回复: 第一个是计算原价,第二个是计算使用优惠券后的价格,我们可以将第一个去掉,这里只是冗余了一个payTotalMoney。

    2019-08-08
收起评论
21
返回
顶部