装饰器模式:
装饰器模式:Decorator Pattern
又叫包装模式,在不改变原有对象的基础上,将功能附加到对象上,提供比继承更有弹性的替代方案
(扩展原有对象的功能)
属于结构型模式
装饰器模式的核心是功能扩展
在标配的基础上,透明的、动态的扩展类的功能
装饰器模式主要包含四个角色:
抽象组件(Component): 可以是一个接口或者抽象类,其充当被装饰类的原始对象,对丁了被装饰对象的行为
具体组件(ConcreteComponent): 实现/继承 Component 的一个具体对象,即 被装饰对象
抽象装饰器(Decorator): 用于装饰 ConcreteComponent 的通用装饰器,其内部必然有一个属性指向 Component 抽象组件,其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个 Component 抽象组件,这是强制的通用行为
具体装饰器(ConcreteDecorator): Decorator 的具体实现类,理论上,每个 ConcreteDecorator 都扩展了 Component 对象的一种功能
装饰器模式角色分配符合里氏替换原则、依赖倒置原则,从而满足开闭原则
通用写法:
pattern.decorator.general
应用场景:
给煎饼加鸡蛋、蛋糕加水果、房子装修
为对象扩展一些额外的职责
适用于以下场景:
1、用于扩展一个类的功能或给一个类添加附加职责
2、动态的给一个对象添加功能,这些功能可以再动态的撤销
3、需要为一批的兄弟类进行改装或加装功能
煎饼实例:
创建一个煎饼的抽象类 Battercake
创建一个基础套餐的煎饼 BaseBattercake
创建一个扩展套餐的抽象类(装饰器) BattercakeDecotator
创建鸡蛋装饰器EggDecorator
创建香肠装饰器 SausageDecorator
客户端组装
pattern.decorator.battercake.v2
sls服务监控孔明日志格式的包装实例:
将项目中的日志封装成 Json 格式的日志再打印
创建一个装饰器类 DecoratorLogger
创建一个具体装饰器类 JsonLogger
pattern.decorator.logger
装饰器模式的本质特征就是 将原有类的附加功能抽离出来,简化原有类的逻辑
约束:一定是通过一个构造方法来传递同个【继承】体系的参数
源码中的体现:
JDK:最明显的类就是 IO 相关的类
BufferedReader、InputStream、OutputStream
Spring:TransactionAwareCacheDecorator 类,用于处理事务缓存的
MVC 中的 HttpHeadResponseDecorator 类
MyBatis: org.apache.ibatis.cache.Cache 类,处理缓存的设计,
FifoCache 类,先入先出算法的缓存
LruCache 类,最近最少使用的缓存
TransactionCache 类,事务相关的缓存
装饰器模式 和 代理模式 对比
从 UML 类图 和 通用代码是实现上看,二者几乎一模一样,以上是对应关系:
代理模式装饰器模式
SubjectComponent
RealSubjectConcreteComponent
ProxyDecorator
装饰器模式是代理模式的一个特殊应用,但是二者设计模式所面向的功能扩展面不一样:
装饰器模式:强调自身功能的扩展
(用户自己说了算,要加什么由调用者控制)透明扩展、可动态定制的扩展
Decorator 所做的就是增强 ConcreteComponent 的功能(也可能是减弱),主体对象是 ConcreteComponent , 着重类功能的变化
代理模式:强调对代理过程的控制
Proxy 完全掌握对 RealSubject 的访问控制,proxy 可以决定对 RealSubject 进行功能扩展(功能缩减),主体对象是 Proxy
举例说明:
假设现在小明想租房,那么势必会有一些事务发生:房源搜索,联系房东谈价格。。。
从代理模式进行思考:
那么小明只需要找到一个房租中介,让他去干房源搜索,联系房东谈价格这些事情,小明只需等待通知然后浮点中介费就行了
从装饰器模式进行思考:
因为装饰器模式强调自身功能扩展,那么小明自身就要增加房源搜索能力的扩展,联系房东谈价格能力的扩展,通过相应的装饰器,提升自身能力,一个人做完所有的事情
优点:
装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下 动态的给一个对象扩展功能,即插即用
用过使用不同的装饰类以及这些装饰类的排列组合,可以实现不同的效果
装饰器完全遵守开闭原则
缺点:
会出现更多的代码,更多的类,增加程序复杂度
动态装饰时,多层装饰时会更复杂
作业:
2、使用装饰器模式实现一个可根据权限动态扩展功能的导航条。
/homework/tasks/7e7e7f7ff7g5egc4g6agf0