装饰器模式

装饰器模式:

装饰器模式: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

posted @ 2020-06-18 14:13  离散音符  阅读(192)  评论(0编辑  收藏  举报