装饰者模式及其典型应用
1、什么是装饰者模式
装饰者模式定义:在不改变原有对象的基础上,将功能附加到对象上。装饰者模式允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供额外的功能。
2、装饰者模式的特性
(1)意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
(2)主要解决:
一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
(3)何时使用:
在不想增加很多子类的情况下扩展类。
(4)如何解决:
将具体功能职责划分,同时继承装饰者模式。
(5)关键代码:
1)Component 类充当抽象角色,不应该具体实现。
2)修饰类引用和继承 Component 类,具体扩展类重写父类方法。
3、装饰者模式的优缺点及其应用场景
(1)优点:
1)装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以在不改变原有对象的基础上动态扩展一个实现类的功能。
2)使用不同的组合可以实现不同的效果;
3)符合开闭原则。
(2)缺点:
多层装饰比较复杂。
(3)使用场景:
1)扩展一个类的功能或给一个类添加职责。
2)动态增加功能,动态撤销。
(4)注意事项:
可代替继承。
4、装饰者模式应用示例
(1)示例场景:
假设相机现在有拍照功能,我们要给其添加美颜和滤镜功能。添加新功能由不能影响旧功能和接口,要符合开闭原则。示例类图:
(2)代码示例:
相机组件接口:
//接口
interface Component{
void operation();
}
原始对象拍照功能:
//原始功能
class ConcreteComponent implements Component{
@Override
public void operation() {
System.out.println("拍照");
}
}
使用拍照功能:
public class DecoratorTest {
public static void main(String[] args){
//原始功能测试
Component component = new ConcreteComponent();
component.operation();
}
}
//输出
//拍照
下面使用装饰者模式,添加美颜和滤镜功能,在不改变拍照功能的基础上。
添加一个装饰者类:在装饰类中传入原始组件接口:
//使用装饰者模式添加新功能
abstract class Decorator implements Component{
Component component;
public Decorator(Component component){
this.component = component;
}
}
添加一个子类,继承自装饰者类,添加美颜功能:
//添加美颜功能
class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void operation() {
component.operation();
System.out.println("添加美颜.");
}
}
添加一个子类,继承自装饰者类,添加滤镜功能:
//添加滤镜功能
class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void operation() {
component.operation();
System.out.println("添加滤镜.");
}
}
测试美颜功能:
public class DecoratorTest {
public static void main(String[] args){
//装饰者功能测试:测试美颜功能
Component component1 = new ConcreteDecorator(new ConcreteComponent());
component1.operation();
}
}
输出:
拍照
添加美颜
测试滤镜功能(美颜+滤镜):
public class DecoratorTest {
public static void main(String[] args){
//装饰者功能测试:添加滤镜功能
ConcreteDecorator2 concreteDecorator2 = new ConcreteDecorator2(new ConcreteDecorator(new ConcreteComponent()));
concreteDecorator2.operation();
}
}
输出示例:
拍照
添加美颜.
添加滤镜.
可以看出,装饰者模式可以动态地扩展一个类的功能或添加职责。
5、装饰者模式在Java框架中的典型应用
1)Servlet Api中带有Wrapper结尾的类;
2)tomcat中的javax.http.HttpServletRequestWrapper类是装饰者模式的典型应用,该类定义源码如下:
public class HttpServletRequestWrapper extends ServletRequestWrapper implements
HttpServletRequest {
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
*
* @throws java.lang.IllegalArgumentException
* if the request is null
*/
public HttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
//...其他方法
}
ServletRequestWrapper类的定义如下:
public class ServletRequestWrapper implements ServletRequest {
private ServletRequest request;
/**
* Creates a ServletRequest adaptor wrapping the given request object.
*
* @param request The request to wrap
*
* @throws IllegalArgumentException if the request is null
*/
public ServletRequestWrapper(ServletRequest request) {
if (request == null) {
throw new IllegalArgumentException("Request cannot be null");
}
this.request = request;
}
//...其他方法
}
可以看到,该类传入了ServletRequest参数,类中的方法的实现也都是传递给Request类去实现。通过使用Wrapper类,可以对ServletRequest进行扩展功能和添加职责。
3)javax.servlet.http.HttpServletResponseWrapper同理。
本文源代码:
https://github.com/JianfuYang/2020-yjf-review/tree/master/src/designpatterns/decorator
声明:本文部分内容整理来源于网络,仅做个人学习使用!侵删~
本文部分内容参考链接:
https://www.runoob.com/design-pattern/decorator-pattern.html