经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式-装饰器模式
来源:cnblogs  作者:公众号JavaStorm  时间:2019/6/10 13:43:46  对本文有异议

微信关注公众号 JavaStorm 获取最新内容。

装饰器模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活;它允许向一个现有的对象添加新的功能,同时又不改变其结构。==装饰器模式属于结构型模式==。

UML 类图

装饰器模式

  • Component:接口,定义一个抽象接口装饰对象与真实对象具有相同的接口,以便装饰器动态的添加职责。
  • ConcreteComponent: 接口的具体对象。
  • Decorator:装饰类,继承了 Component , 从外类来拓展 Component 的功能 并且持有一个 Component 的引用,通过构造器实例化,从而实现对真实对象的职责装饰增强。
  • ConcreteDecorator:具体装饰类,用于给实际对象添加职责。

使用场景

现在有一个场景:煎饼果子,科技园上班族早上去买煎饼果子(Pancake),有的人要加鸡蛋 (Egg)、有的人加火腿 (Ham)、有的人加生菜 (Lettuce)。有的土豪煎饼果子来一套全都要。现在我们来定义煎饼烹饪实现。(ps:留一个功能读者自己实现:不同的套餐价格是不一样的,如何计算出不同煎饼果子的价格?有兴趣的读者可以留言或者微信公众号后台留言)。

代码实现

代码可以左右滑动

  1. 先定义煎饼接口也就是我们的被装饰类,以及烹饪的方法 。
  1. package com.zero.headfirst.decorator;
  2. public interface Pancake {
  3. /**
  4. * 烹饪方法
  5. */
  6. void cook();
  7. }
  1. 定义一个乞丐版煎饼,被装饰对象。
  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 被装饰对象:定义最基本的乞丐版煎饼,啥都没加
  4. */
  5. public class BeggarPancake implements Pancake {
  6. @Override
  7. public void cook() {
  8. System.out.println("乞丐版基本煎饼");
  9. }
  10. }
  1. 定义抽象装饰类 煎饼果子装饰器 PancakeDecorator:抽象装饰器角色,实现煎饼接口(被装饰器接口),持有被装饰器的引用 (pancake)将烹饪行为转发具体的装饰器。
  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 抽象装饰器角色,实现煎饼接口(被装饰器接口),持有被装饰器的引用将烹饪行为转发具体的装饰器。
  4. */
  5. public abstract class PancakeDecorator implements Pancake {
  6. private Pancake pancake;
  7. public PancakeDecorator(Pancake pancake) {
  8. this.pancake = pancake;
  9. }
  10. @Override
  11. public void cook() {
  12. if (pancake != null) {
  13. pancake.cook();
  14. }
  15. }
  16. }
  1. 各种具体装饰类对乞丐版煎饼进行不等级别的土豪加工。首先继承 抽象出来的 PancakeDecorator ,重写 cook 方法,实现加工。

    EggDecorator 鸡蛋装饰器:继承 PancakeDecorator,重写 cook 方法。动态添加鸡蛋,然后调用pancake 的cook。

  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 鸡蛋装饰器:覆盖cook方法,加入自身的实现,并且调用父类的cook方法,也就是构造函数中
  4. * EggDecorator(Pancake pancake),这里传入的pancake的cook操作
  5. */
  6. public class EggDecorator extends PancakeDecorator {
  7. public EggDecorator(Pancake pancake) {
  8. super(pancake);
  9. }
  10. @Override
  11. public void cook() {
  12. System.out.println("加一个鸡蛋;");
  13. super.cook();
  14. }
  15. }

火腿装饰器: HamDecorator

  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 火腿装饰器
  4. */
  5. public class HamDecorator extends PancakeDecorator {
  6. public HamDecorator(Pancake pancake) {
  7. super(pancake);
  8. }
  9. @Override
  10. public void cook() {
  11. System.out.println("加一个火腿;");
  12. super.cook();
  13. }
  14. }

生菜装饰器

  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 生菜装饰器
  4. */
  5. public class LettuceDecorator extends PancakeDecorator {
  6. public LettuceDecorator(Pancake pancake) {
  7. super(pancake);
  8. }
  9. @Override
  10. public void cook() {
  11. System.out.println("加生菜;");
  12. super.cook();
  13. }
  14. }
  1. 定义一个煎饼果子摊位。
  1. package com.zero.headfirst.decorator;
  2. /**
  3. * 煎饼果子店
  4. */
  5. public class PancakeShop {
  6. public static void main(String[] args) {
  7. System.out.println("========土豪来了,全都加上。======");
  8. BeggarPancake beggarPancake = new BeggarPancake();
  9. EggDecorator eggDecorator = new EggDecorator(beggarPancake);
  10. HamDecorator hamAndEggDecorator = new HamDecorator(eggDecorator);
  11. LettuceDecorator lettuceAndHamAndEggDecorator = new LettuceDecorator(hamAndEggDecorator);
  12. lettuceAndHamAndEggDecorator.cook();
  13. System.out.println("========苦逼码农来了,只要鸡蛋补补脑。=====");
  14. BeggarPancake beggarPancake1 = new BeggarPancake();
  15. EggDecorator eggDecorator1 = new EggDecorator(beggarPancake1);
  16. eggDecorator1.cook();
  17. }
  18. }
  1. 运行结果
  1. ========土豪来了,全都加上。======
  2. 加生菜;
  3. 加一个火腿;
  4. 加一个鸡蛋;
  5. 乞丐版基本煎饼
  6. ========苦逼码农来了,只要鸡蛋补补脑。=====
  7. 加一个鸡蛋;
  8. 乞丐版基本煎饼

总结

真实世界的装饰: Java I/O。
注意事项与要点

  • 抽象装饰器与具体被装饰对象实现同一个接口。
  • 抽象装饰器持有被装饰器接口对象,以便请求传递。
  • 具体装饰器需要重写抽象装饰器的方法并引用super进行条用,转发请求。

适用场景

  • 拓展一个类的功能。

  • 动态的添加与撤销职责。

### 优点

  • 装饰类与被装饰类只关心自己的核心逻辑,实现了解耦。
  • 方便动态拓展,开闭原则。且比继承灵活。

缺点

  • 如果功能拓展太多,将产生大量的类。
  • 多层装饰会变得复杂。

以上代码可参考我的 GitHub : https://github.com/UniqueDong/zero-design-stu。headfirst包下。欢迎关注公众号: JavaStorm 获取最新文章,也可在后台留言提出意见。收藏与关注是最大的鼓励。

JavaStorm

原文链接:http://www.cnblogs.com/uniqueDong/p/10993186.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号