装饰模式是第三个介绍的模式了.

这个模式没有前面两个那么好理解.,

一, 装饰模式(decorator)的定义.

教材里是这样写的:

动态第给1个对象添加1写额外的职责(功能), 就增加的功能来讲, 装饰模式比生成子类更加灵活.

就咁睇的确很难明白. 但我们起码可以知道一下两点:

1. 装饰模式的作用是增强1个对象(类) 的功能.

2. 它比生成子类更加灵活.

本文着重讲下第2点, 包括什么是生成子类,  为什么装饰模式比它更加灵活.

二, 1个Hunter1(猎人)类的例子.

举1个很简单的例子. 1个猎人类实现1个打猎的接口.

Huntable 接口:

public interface Huntable {public void hunt();
}

猎人类Hunter1:

public class Hunter1 implements Huntable{public void eat(){System.out.println("eating!");}public void hunt(){System.out.println("Hunter is Hunting!");}
}

可见Hunter1这个类实现了Huntable借口.

hunt()方法里只简单重写了hunt()方法.

客户端代码:

Hunter1 h = new Hunter1();
h.hunt();

输出:

Hunter is Hunting!

1个增强hunt()方法的需求:

好了, 现在有1个猎人, 他出去不只是打猎,  他打猎的同时还同时训练它的猎狗, 最后还会给战利品拍一张照片.

也就是需要增强hunt()方法功能.

加上

trainDog() 和 takePic()这个两个方法.

怎么实现呢?

三, 通过添加子类Hunter2方法来增强Hunter1

open-closed principle:

可能有人会觉得. 直接在Hunter1里加上两个方法trainDog () 和  takePic(),  在hunt()里调用这个两个新方法不就完事了吗.

的确, 但是这种做法修改了原有的类,  违反了"封闭-开放原则".

所谓"封闭-开发原则" 就是对修改封闭, 对扩展开放.

在项目中, 很多旧的业务类根本不会让你修改(jar包发布或者你没有权限)

所以我们应该把这个新需求当做1个扩展来处理, 而不是修改旧代码.

其中1个方法就是增加子类.

新增1个Hunter2 类:

public class Hunter2 extends Hunter1{@Overridepublic void hunt(){super.hunt();this.trainDog();this.takePic();}//new function()public void trainDog(){System.out.println("Train the Dog!");}public void takePic(){System.out.println("Take a picture!");}
}

客户端代码:

Hunter2 h2 = new Hunter2();
h2.hunt();

UML:

可见, 这种方法, 只是新增了1个子类, 以及修改客户端代码, 对原来的类代码没有任何修改, 是符合"封闭-修改 原则"的.

这种修改, 增强了原来的类Hunter1 的hunt()功能, 可以说是"装饰"了原来的hunt()方法.

但是这种修改不是很灵活.

比如:   这种猎人是先打猎,再训狗,再拍照的.

如果有一种猎人喜欢先拍照再训狗了,  我们就又要增加1个Hunter1的子类了....

而装饰模式能解决问题.

四, 通过装饰模式来增强Hunter类.

Huntable 接口 和 Hunter类:

首先构造两个相同的接口和类:

public interface Huntable {public void hunt();
}
public class Hunter implements Huntable {public void eat(){System.out.println("eating!");}@Overridepublic void hunt(){System.out.println("Hunter is Hunting!");}
}

Hunter类跟上面的Hunter1类是完全一样的.

下面开始构造新的类来强化hunt()方法.

抽象装饰角色类   HuntOperation:

无论, 是训狗trainDog() 还是拍照takePic() 都是对hunt()的增强.

我们新增1个HuntOperation类,  让它继承Hunter类,  让它能重写hunt()方法.

public abstract class HuntOperation extends Hunter{private Hunter hunter = null;//setting componentpublic HuntOperation(Hunter hunter){this.hunter = hunter;}//actually execute component's hunt() method@Overridepublic void hunt(){if (null != hunter){hunter.hunt();}}
}

注意, 这个类有1个Hunter对象成员.

在hunt()方法里, 执行的实际上是成员Hunter对象的hunt()方法.

具体的装饰行为类 HuntTakePic():

照相类, 就让它继承抽象行为类 HuntOperation类.

public class HuntTakePic extends HuntOperation{public HuntTakePic(Hunter hunter) {super(hunter);}@Overridepublic void hunt(){super.hunt();this.takePic();}public void takePic(){System.out.println("Taking a Picture!");}
}

可见, 它先执行性成员Hunter对象的hunt()方法, 在执行自己的照相方法.

具体的装饰行为类 HuntTrainDog():

同样, 这个类也继承HuntOperation.

先执行Hunter对象的hunt()方法, 再执行自己的TrainDog方法.

public class HuntTrainDog extends HuntOperation{public HuntTrainDog(Hunter hunter) {super(hunter);// TODO Auto-generated constructor stub}@Overridepublic void hunt(){super.hunt();this.trainDog();}public void trainDog(){System.out.println("Training the dog!");}}

客户端代码:

客户端代码如下:

先构建1个Hunter对象h, 然后再基于h构建HuntTakePic htp,  然后在基于htp构建HuntTrainDog 对象htd.

最后执行htd的hunt()方法.

         Hunter h = new Hunter();HuntTakePic htp = new HuntTakePic(h);HuntTrainDog htd = new HuntTrainDog(htp);htd.hunt();

实际上, 就先执行Hunter对象的hunt(), 再执行HuntTakePic对象的hunt(), 最后才执行HuntTrainDog对象的hunt()

输出:

Hunter is Hunting!
Taking a Picture!
Training the dog!

UML:

装饰模式的灵活性:

好了, 这种模式一样能增强Hunter类的hunt()

那么它到底比第一种方法灵活在哪里呢.

很简单, 假如另1类猎人想调换训狗, 和照相的顺序, 只需修改客户端的构建循序, 并需要再新增1个子类.

这就是装饰模式的灵活性.

有人会觉得, 装饰模式同样需要增加子类啊,  实际上, 假如我们为Hunter的hunt()再增加1个子行为, 例如给猎物剥皮.

那么只需要增加1个抽象行为HuntOperation的子类, 而不是Hunter的子类..

五, 小结

其实想深一层, 装饰模式之所以叫装饰模式.

是因为装饰不能改变原有的功能的行为.

就如上面的例子,  Hunter里原来的hunt()方法没有改变,  只是增加了一些额外的功能.

所以如果需要从根本上改变Hunter里hunt()的代码, 装饰模式就不适用了,  还是建议用增加Hunter子类的方法.

装饰模式(Decorator)简介相关推荐

  1. 二十四种设计模式:装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern) 介绍 动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活. 示例 有一个Message实体类,某个对象对它的操作有Insert ...

  2. 设计模式(13):结构型-装饰模式(Decorator)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  3. 七、装饰模式(Decorator Pattern)

    一.介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:使用继承实现类的功能的扩展,有时子类会过多的问题. 应用实例: 1.一幅照片,将它放入玻 ...

  4. 装饰模式Decorator

                                                               装饰模式Decorator /*** 抽象构件角色* @author InJava ...

  5. 《研磨设计模式》chap22 装饰模式Decorator(1)模式简介

    场景:算员工奖金,各种奖金,有个人销售奖,团队奖,环比增加销售奖等等 1. 正常编码 public class Prize {//计算某人在某段时间内的奖金,有些参数在演示中并不会使用, public ...

  6. 装饰模式(Decorator)

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

  7. 设计模式之装饰模式(Decorator)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  8. c语言装饰,C++设计模式之装饰模式(Decorator)

    装饰模式是一种经典的类功能扩展模式,其精髓在装饰类使用继承加聚合的方式获得接口和要实现对象,然后通过自己实现扩展接口 作用装饰模式通过装饰类动态地将责任附加到对象上,若要扩展功能,无需通过继承增加子类 ...

  9. 《研磨设计模式》chap22 装饰模式Decorator(4)AOP+总结

    1. AOP面向方面编程 共性功能 AOP调用示意图 public class SaleModel { private String goods; //销售的商品 public String getG ...

最新文章

  1. iframe父子页面交互
  2. Python Numba实现GPU加速
  3. QT入门安装篇+helloworld(辛酸血泪)
  4. Ironport对邮件主题中包括特殊字符的过滤
  5. SAP CRM和C4C的订单Number range
  6. 在 LinearLayout里addView一个图表
  7. 详解RPC远程调用和消息队列MQ的区别
  8. i2c通信 msp430g2553_msp430g2553的IIC通信
  9. Global Average Pooling对全连接层的可替代性分析(转)
  10. 利用gsm模块自动收发短信
  11. spring使用之旅(二) ---- AOP的使用
  12. Python输出函数print()总结(python print())
  13. 微信windows版本体验报告
  14. 【CAN】 PCAN Explorer5 常用操作使用简介
  15. 达人评测 小米笔记本pro14和联想yoga14s 选哪个好
  16. Linux性能优化实战学习笔记:第四十六讲=====实战分析
  17. websocket+cdn架构部署
  18. 使用Tensorflow训练LSTM+Attention中文标题党分类
  19. 令我“细思极恐”的Faster-R-CNN
  20. Python实现将位图描摹为彩色矢量 svg 图片的源代码,Python实现位图转彩色矢量代码

热门文章

  1. BUU——WMCTF2020 - easy_re
  2. 密码技术--国密SM4分组密码算法及Go语言应用
  3. 02-Linux Kernel(armv8-aarch64)的原子操作的底层实现
  4. MTK的LK代码异常向量表解析
  5. Win10 EPROCESS 断链
  6. c++对象长度之空类(1)
  7. 2020-11-10(回传递过程)
  8. 服务器被入侵了?反手溯源出入侵者画像【网络安全】
  9. 【安全实战】红队攻防技术
  10. MySQL创建用户(CREATE USER)