文章目录
一、装饰器模式的简介
1. 什么是装饰器模式
装饰器模式(Decorator Pattern) 是为了达到可以为一个现有对象添加新的功能同时又不改变其结构的设计模式,这种设计模式属于结构性设计模式。通常情况下,我们想要拓展一个已有类的功能或职责都会采用继承的方式来实现,但是这种方式随着继承层级的增加,静态特征会越来越多,子类会很膨胀,所以我们就需要一种手段来减少继承带来的子类膨胀问题,这就是装饰器模式。
2. 装饰器模式的业务场景
装饰器模式常用在两种情况:
- 用于拓展一个类的功能或职责
- 用于对象功能的拓展,这种拓展是可插拔,可撤销的。
装饰器模式有个经典的例子就是孙悟空的七十二变。当孙悟空没有施展变化的时候,他可以正常的说出师傅师傅。当孙悟空变成蜜蜂的时候,他虽然依旧可以说出师傅师傅,但是此时使用的语言就变成了蜜蜂的嗡嗡嗡,虽然变成了蜜蜂,但是这只蜜蜂本质上还是孙悟空。下面我们用代码实现以下这个逻辑。
二、装饰器模式的实现
1. 代码实现
(1) 创建实体接口
public interface MonkeySun {
void say();
}
(2) 创建实现类
public class MonkeyKing implements MonkeySun {
// 齐天大圣
@Override
public void say() {
// 叫师傅
System.out.println("唐sensi!");
}
}
(3) 创建抽象装饰类
public abstract class MonkeySunDecorator implements MonkeySun {
protected MonkeySun monkeySun;
// 强制子类实现有参构造
public MonkeySunDecorator(MonkeySun monkeySun) {
super();
this.monkeySun = monkeySun;
}
abstract void sayDecorator();
// 默认采用已有方法,这样在使用的时候就可以使用未被装饰的API
@Override
public void say() {
monkeySun.say();
}
}
(4) 创建装饰实现类
public class MonkeyBeeDecorator extends MonkeySunDecorator {
public MonkeyBeeDecorator(MonkeySun monkeySun) {
super(monkeySun);
// TODO Auto-generated constructor stub
}
@Override
void sayDecorator() {
super.say();
System.out.println("嗡嗡嗡");
}
}
(5) 测试代码
public class Test {
public static void main(String[] args) {
MonkeySunDecorator monkeyBeeDecorator = new MonkeyBeeDecorator(new MonkeyKing());
monkeyBeeDecorator.say();
monkeyBeeDecorator.sayDecorator();
}
}
2. 装饰器模式的实现分析
如图:
装饰器模式其实主要就分为两个角色:
- 被装饰对象: 在这里我们可以理解为一个需要被装饰的产品。
- 装饰器: 这里的装饰器分为两部分,第一部分就是装饰器的父类,我们通常使用一个抽象类来描述。这个抽象类通常实现了被装饰者的接口并将被装饰者作为局部变量通过构造参数传入。这里可能有同学不明白一个问题,为什么需要既实现接口,又要作为参数传入维护引用的问题。 这里为大家解答一下:实现接口是因为装饰器本质上还是之前的对象,使用实现接口的形式可以使业务方在不想要使用装饰方法的情况下使用原有的接口API,而作为参数传入也是为了可以获取到未被装饰前对象的API相关信息。
三、装饰器模式的特点
1. 装饰器模式的优劣势
优点:
- 装饰类和被装饰类可以独立发展,不会发生耦合
缺点:
- 多层装饰提升了代码复杂度
2. 装饰器模式在JDK中的引用
JDK中的IO结构的搭建就是引用了装饰器模式,感兴趣的同学可以翻阅下IO类的源码学习一下。
好了,今天的内容到此结束,如果还有疑问的同学可以私信我或在评论区留言,我会在第一时间为你解答。觉得有收获的小伙伴请记得一键三连,关注博主不要走丢,拒当白嫖党~