DesignPattern - 装饰器模式【结构型】
# 一、装饰器模式介绍
装饰器模式(Decorator Pattern)也叫包装设计模式,属于结构型模式,它是作为现在的类的一个包装,允许向一个现有的对象添加新的功能,同时又不改变其结构。
给对象增加功能,一般两种方式 继承 和 关联组合 。装饰器模式使用的是关联组合,将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用对象的行为来增强功能,比使用继承更加灵活。
核心组成
- 抽象组件(Component):定义组件的方法
- 具体组件(ConcreteComponent):Component 的具体实现,是要装饰的具体对象,即被装饰者
- 抽象装饰器(Decorator):定义具体装饰者的行为规范,和 Component 角色有相同的接口,持有组件(Component) 对象的实例引用
- 具体装饰器(ConcreteDecorator):负责给 Component 对象装饰具体的附加功能
注意:装饰者和被装饰者有相同的超类(Component)
应用场景
- 以动态、透明的方式给单个对象添加职责,但又能不改变其结构
- JDK 源码里应用的最多的就是 IO 流,大量使用装饰设计模式(InputStream、BufferedInputStream...)
优点
- 装饰器模式与继承关系的目的都是扩展对象的功能,但装饰器模式可以提供比继承更多的灵活性
- 使用不同的具体装饰器以及这些装饰类的排列组合,可以创造出很多不同行为的组合,原有代码无须改变,符合”开闭原则“
缺点
- 装饰器模式增加了许多子类,如果过度使用会使程序变得很复杂(多层包装)
- 增加系统的复杂度,加大学习与理解的难度
# 二、装饰器模式代码实现
创建抽象组件类:
/**
* 抽象组件:枪
*
* @author GitLqr
*/
public abstract class Gun {
String name;
public Gun(String name) {
super();
this.name = name;
}
/**
* 攻击力
*/
public abstract float attack();
/**
* 后坐力
*/
public abstract float recoil();
@Override
public String toString() {
return name + "的攻击力为: " + attack() + " , 后坐力为:" + recoil();
}
}
创建具体组件类:
/**
* 具体组件:UMP9
*
* @author GitLqr
*/
public class Ump9Gun extends Gun {
public Ump9Gun() {
super("UMP9");
}
@Override
public float attack() {
return 100;
}
@Override
public float recoil() {
return 20;
}
}
创建抽象装饰器类:
/**
* 抽象装饰器:配件
*
* @author GitLqr
*/
public abstract class Part extends Gun {
// 持有组件引用(注意:这个组件可能是已经被装饰过的)
Gun gun;
public Part(String name, Gun gun) {
super(name);
this.gun = gun;
}
@Override
public String toString() {
return "装配【" + name + "】,攻击力为: " + attack() + " , 后坐力为:" + recoil();
}
}
创建具体装饰器类:
/**
* 具体装饰器:消声器
*
* @author GitLqr
*/
public class MufflerPart extends Part {
public MufflerPart(Gun gun) {
super("消声器", gun);
}
@Override
public float attack() {
return gun.attack() - 5;
}
@Override
public float recoil() {
return gun.recoil() + 5;
}
}
/**
* 具体装饰器:火焰子弹
*
* @author GitLqr
*/
public class FireBulletPart extends Part {
public FireBulletPart(Gun gun) {
super("火焰子弹", gun);
}
@Override
public float attack() {
return gun.attack() + 30;
}
@Override
public float recoil() {
return gun.recoil() + 5;
}
}
使用:
public static void main(String[] args) {
Gun gun = new Ump9Gun();
System.out.println(gun); // UMP9的攻击力为: 100.0 , 后坐力为:20.0
gun = new MufflerPart(gun);
System.out.println(gun); // 装配【消声器】,攻击力为: 95.0 , 后坐力为:25.0
gun = new FireBulletPart(gun);
System.out.println(gun); // 装配【火焰子弹】,攻击力为: 125.0 , 后坐力为:30.0
// Gun gun = new FireBulletPart(new MufflerPart(new Ump9Gun()));
}
# 三、装饰器模式在 JDK 源码 IO 流中的应用
- 抽象组件:InputStream
- 具体组件:FileInputStream、ByteArrayInputStream
- 抽象装饰器:FilterInputStream
- 具体装饰器:BufferedInputStream、DataInputStream
抽象组件 InputStream 定义了 read()
方法:
public abstract class InputStream implements Closeable {
...
public abstract int read() throws IOException;
}
具体组件 FileInputStream 实现了 read()
方法:
public class FileInputStream extends InputStream {
...
public int read() throws IOException {
return read0();
}
private native int read0() throws IOException;
}
抽象装饰器 FilterInputStream 继承自抽象组件 InputStream,持有组件对象实例引用:
public class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;
...
}
具体装饰器 BufferedInputStream 对 read()
进行增强,增加缓存功能:
public class BufferedInputStream extends FilterInputStream {
protected volatile byte buf[];
...
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
...
}
使用:
// 添加了Buffer缓冲功能
InputStream inputStream = new BufferedInputStream(new FileInputStream(""));
- 01
- Flutter - 危!3.24版本苹果审核被拒!11-13
- 02
- Flutter - 轻松搞定炫酷视差(Parallax)效果09-21
- 03
- Flutter - 轻松实现PageView卡片偏移效果09-08