文章目录

  • 生日蛋糕
  • 正常套路
    • 缺点
  • 装饰模式救场
    • 蛋糕接口
    • 奶油蛋糕
    • 蛋糕装饰类
    • 樱桃
    • 草莓
    • 火龙果
    • 测试类
    • 测试结果
  • 总结
  • 最后

生日蛋糕

过几天就是小美的生日了,小帅不敢怠慢,打算定一个奶油蛋糕,好好庆祝一下。

店里标准的奶油蛋糕上面就一层奶油,也没有其他的配料,看着不大气,万一小美不喜欢可就糟了。

小美喜欢吃水果,小帅就想在蛋糕上加点水果,就找老板商量:能不能多加几种水果,我可以另外加钱。

老板眉开眼笑:当然可以啊,我们这里有樱桃,草莓,火龙果你要加什么哦?

这是我们的价目表:

奶油蛋糕:200元
巧克力蛋糕:230元
樱桃:30元
草莓:15元
火龙果:10元

我们店有两种蛋糕,一种是奶油蛋糕,另一种是巧克力蛋糕,每种蛋糕都可以另外加水果哦。

正常套路

按照正常的套路,如果用代码实现买蛋糕的功能,我们一般会给每种蛋糕和水果组合设计一种类。

如果我们想要在奶油蛋糕上加樱桃就新建一个奶油蛋糕樱桃类(CreamCakeAndCherry);

如果奶油蛋糕上加草莓就新建一个奶油蛋糕草莓类(CreamCakeAndStrawberry);

如果巧克力蛋糕上加樱桃就新建一个巧克力蛋糕樱桃类(ChocolateCakeAndCherry)。

还有奶油蛋糕火龙果类,巧克力蛋糕草莓类,巧克力蛋糕火龙果类,如果蛋糕店又增加了一种千层蛋糕,还有千层蛋糕草莓类,千层蛋糕樱桃类。。。

如果再加几种水果。。。完蛋了,类已经爆炸了。。。

缺点

这么写有什么缺点呢?

1.最明显的是类太多了,看得眼花缭乱,增加了维护的成本。
2.一旦出现的新蛋糕或水果,又要增加一大堆类。
3.如果蛋糕和水果的价格改变了,要改很多很多类,严重违反了开闭原则:类应该对扩展开发,对修改封闭。

小帅作为一个有追求的程序员,当然不会满足这种做法,小帅想起了装饰模式,水果不是刚好装饰蛋糕的吗?正好符合装饰模式的应用场景,赶紧试一下吧。

装饰模式救场

装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。

装饰模式的类图如下:

Component: 抽象构件
ConcreteComponent: 具体构件
Decorator: 抽象装饰类
ConcreteDecorator: 具体装饰类


这里要注意一下Decorator装饰类,它维持了一个指向component对象的指针,接口方法的实现,都是调用这个component对象的方法实现的,Decorator类本身只是调用了component对象已有的功能,这是装饰模式的精髓所在

这么说有点不好理解,看一下下面的例子就能明白了。

蛋糕接口

public interface Cake {public String getDescription();public BigDecimal cost();
}

奶油蛋糕

public class CreamCake implements Cake{public String getDescription() {return "奶油蛋糕";}public BigDecimal cost() {return BigDecimal.valueOf(200);}}

蛋糕装饰类

public class CakeDecorator implements Cake{Cake cake;public CakeDecorator(Cake cake) {this.cake = cake;}public String getDescription() {return cake.getDescription();}public BigDecimal cost() {return cake.cost();}}

樱桃

public class Cherry extends CakeDecorator{public Cherry(Cake cake) {super(cake);}@Overridepublic String getDescription() {return cake.getDescription() + ",添加樱桃";}@Overridepublic BigDecimal cost() {return BigDecimal.valueOf(30).add(cake.cost());}
}

草莓

public class Strawberry extends CakeDecorator{public Strawberry(Cake cake) {super(cake);}@Overridepublic String getDescription() {return cake.getDescription() + ",添加草莓";}@Overridepublic BigDecimal cost() {return BigDecimal.valueOf(15).add(cake.cost());}
}

火龙果

public class DragonFruit extends CakeDecorator{public DragonFruit(Cake cake) {super(cake);}@Overridepublic String getDescription() {return cake.getDescription() + ",添加火龙果";}@Overridepublic BigDecimal cost() {return BigDecimal.valueOf(10).add(cake.cost());}
}

测试类

public class Test {public static void main(String[] args) {// 标准奶油蛋糕Cake cake = new CreamCake();// 添加樱桃cake = new Cherry(cake);// 添加草莓cake = new Strawberry(cake);// 添加火龙果cake = new DragonFruit(cake);// 双份樱桃,土豪啊cake = new Cherry(cake);System.out.println(cake.getDescription());System.out.println("合计:" + cake.cost());}
}

测试结果

奶油蛋糕,添加樱桃,添加草莓,添加火龙果,添加樱桃
合计:285

调用过程如下:

装饰模式的调用链,看起来有点像递归调用,装饰类都是附加在其他类上的,但是最重要的还是调用链最底层的实现类。

总结

装饰模式的优点:

1.比继承更灵活,用继承实现的类似功能的话,会产生许多新类,就像上文提到的”类爆炸”。装饰模式可以提供了更加灵活的添加职责的方式,可以在运行时动态地新增和删除职责。

2.通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

3.具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”

装饰模式的缺点:

1.使用装饰模式进行系统设计时将产生很多小对象,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。

2.这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

最后

小美吃着蛋糕,露出开心的笑容:好多樱桃哦,我好喜欢!
小帅:知道你喜欢吃水果,我特意让老板加了两份樱桃呢。
小美:程序员的心思果然细腻,哈哈。

代码链接

装饰模式--小美的生日蛋糕相关推荐

  1. java i o不会的地方_Java I/O 好复杂,傻傻分不清楚,别担心,我们有线索了。。。...

    IO 类图 小帅最近在学Java的IO类库,这么多类看得小帅人头昏眼花,常常是学了这个类,忘了那个类,再过一阵子就全忘了... 每次用到的时候,小帅都要重新读文档,看代码,如此循环,身心疲惫. 小帅没 ...

  2. 一件登录facebook_Facebook抵制抵制是防火的,那是一件好事

    一件登录facebook Mark Zuckerberg isn't too worried about 25 of Facebook's biggest spenders "pausing ...

  3. java i= 0001_Java I/O 好复杂,傻傻分不清楚,别担心,我们有线索了。。。

    IO 类图 小帅最近在学Java的IO类库,这么多类看得小帅人头昏眼花,常常是学了这个类,忘了那个类,再过一阵子就全忘了... 每次用到的时候,小帅都要重新读文档,看代码,如此循环,身心疲惫. 小帅没 ...

  4. java的内容好复杂_Java I/O 好复杂,傻傻分不清楚,别担心,我们有线索了……...

    IO 类图 小帅最近在学Java的IO类库,这么多类看得小帅人头昏眼花,常常是学了这个类,忘了那个类,再过一阵子就全忘了... 每次用到的时候,小帅都要重新读文档,看代码,如此循环,身心疲惫. 小帅没 ...

  5. 戴上装饰者模式的眼镜,看透Java I/O

    文章目录 IO 类图 看个例子 装饰者模式 OutputStream家族类: 清晰起来了 InputStream家族类: Writer家族类: Reader家族类: 再看个例子 最后的话 IO 类图 ...

  6. 了解设计模式 之 结构模式(四) -- 装饰模式

    4. 装饰模式(Decorator Pattern) 装饰模式顾名思义,就是给对象进行一些装饰,让他在原有的基础上动态的添加额外的职责.就好象一个女人,你可以给她"装饰"上漂亮的衣 ...

  7. Day22 设计模式之装饰模式

    设计模式及其作用 设计模式概念 一套被多数人知晓.经过分类编目的.反复使用的优秀代码设计经验的总结. 特定环境下特定问题的处理方法. 设计模式的作用 重用设计和代码 重用设计比重用代码更有意义,自动带 ...

  8. 设计模式之装饰模式(Java实现)

    "怎么了,鱼哥?" "唉,别提了,网购了一件衣服,结果发现和商家描述的差太多了,有色差就算了,质量还不好,质量不好就算了,竟然大小也不行,说好的3个X,邮的却是一个X的, ...

  9. 装饰模式(Decorator)

    1.概念 装饰模式动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活,属于结构性模式一种. 2.模式结构 抽象组件角色(Component):定义一个对象接口,以规范准备接受 ...

最新文章

  1. m1mac安装linux,M1 Mac 能安装 Ubuntu 和 Linux 了 ??
  2. 程序员面试题精选100题(63)-数组中三个只出现一次的数字[算法]
  3. yum 安装 phpmyadmin
  4. c#中用声音提示报警(转)
  5. i++与++i的区别,使用实例说明
  6. php静态数组变量初始化,为什么数组初始化时,赋值不能是常量?
  7. Bailian4020 缺少的扑克牌【set】
  8. 【前端技术】一篇文章搞掂:微信小程序
  9. 向贵人讨教,实现共赢
  10. 多页Excel转换成PDF时如何保存为单独文件
  11. spark操作读取hbase实例
  12. Tcl语言入门(一)基本知识
  13. 百度云、阿里云先后发布通告:中国电信南北互通存异常
  14. 华为技术专家深度解析Java线程状态
  15. html中电子邮件地址怎么写,电子邮件地址怎么写
  16. printf函数打印二进制
  17. 四级网络工程师笔记-操作系统(中)
  18. 高速窄脉冲峰值保持设计
  19. 如何强制关闭进程linux,4种强制关闭Ubuntu中无响应应用程序的方法
  20. 入驻QQ一天就爆满,Midjourney中文版来了

热门文章

  1. electron 开发程序禁用gpu渲染
  2. ACM-ICPC 2018 南京赛区网络预赛 E AC Challenge
  3. 使用免费的CDN平台jsDelivr搭建个人cdn资源网盘
  4. 小鹏G3 XPilot ---APA自动泊车系统
  5. 广元高考2021成绩查询,2021广元市地区高考成绩排名查询,广元市高考各高中成绩喜报榜单...
  6. [HNOI 2012] 永无乡
  7. mysqldumpnbsp;参数说明
  8. 第七届科技节微电影比赛须知
  9. 区块链技术与密码学联系
  10. js点击指定范围之外触发的方法