点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。
本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。
前言
- 23种设计模式速记
- 单例(singleton)模式
- 工厂方法(factory method)模式
- 抽象工厂(abstract factory)模式
- 建造者/构建器(builder)模式
- 原型(prototype)模式
- 享元(flyweight)模式
- 外观(facade)模式
- 适配器(adapter)模式
- 持续更新中......
23种设计模式快速记忆的请看上面第一篇,本篇和大家一起来学习装饰模式相关内容。
模式定义
在不改变原有对象的基础上,将功能附加到对象上。
动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
解决的问题
扩展一个类的功能或给一个类添加附加职责。
模式组成
组成(角色) | 作用 |
---|---|
抽象构件(Component) | 给出一个抽象接口,以规范准备接收附加责任的对象 |
具体构件(ConcreteComponent) | 定义一个将要接收附加责任的类 |
装饰角色(Decorator) | 持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口 |
具体装饰角色(ConcreteDecorator) | 负责给构件对象“贴上”附加的责任 |
实例说明
实例概况
- 背景:隔壁老王创业准备开发一款视频软件
- 冲突:调研市场发现有的用户需要自动添加美颜,有的需要自动添加滤镜
- 解决方案:通过使用装饰模式在视频的基础上,能根据不同用户喜好添加相应功能
使用步骤
步骤1:定义Component抽象构件,也就是定义视频软件基础接口
abstract class Component {
//抽象的方法
public abstract void operation();
}
Component是一个接口或者是抽象类,它定义了最核心的对象,也就是最原始的对象。
步骤2:定义ConcreteComponent具体构件,也就是实现一个视频软件的基本功能
class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("视频软件直播.");
}
}
ConcreteComponent是最核心,最原始、最基本的接口或抽象类的实现,是我们要装饰的对象。
步骤3:定义Decorator装饰角色,是抽象类,聚合了Component接口
abstract class Decorator extends Component {
private Component component=null;
//通过构造函数传递被修饰者
public Decorator(Component component){
this.component=component;
}
//委托给被修饰者执行
@Override
public void operation() {
this.component.operation();
}
}
步骤4:具体装饰角色,A用户需要添加美颜功能
class ConcreteDecoratorA extends Decorator {
//定义被修饰者
public ConcreteDecoratorA(Component component) {
super(component);
}
//定义自己的修饰方法
private void decorator(){
System.out.println("添加美颜.");
}
@Override
public void operation() {
this.decorator();
super.operation();
}
}
步骤5:具体装饰角色,B用户需要添加滤镜功能
class ConcreteDecoratorB extends Decorator {
//定义被修饰者
public ConcreteDecoratorB(Component component) {
super(component);
}
//定义自己的修饰方法
private void decorator(){
System.out.println("添加滤镜.");
}
@Override
public void operation() {
this.decorator();
super.operation();
}
}
步骤6:给不同的用户在视频直播的时候添加不同的功能
public class DecoratorPattern {
public static void main(String[] args) {
// 添加美颜
Component componentA = new ConcreteDecoratorA(new ConcreteComponent());
componentA.operation();
System.out.println();
// 添加滤镜
Component componentB = new ConcreteDecoratorB(new ConcreteComponent());
componentB.operation();
System.out.println();
// 添加美颜和滤镜
Component component = new ConcreteDecoratorA(new ConcreteDecoratorB(new ConcreteComponent()));
component.operation();
}
}
输出结果
添加美颜.
视频软件直播.
添加滤镜.
视频软件直播.
添加美颜.
添加滤镜.
视频软件直播.
优点
- 不改变原有对象的情况下给一个对象扩展功能;
- 使用不同的组合可以实现不同的效果;
- 符合开闭原则
缺点
- 多层的装饰会使系统比较复杂。
即一个实现类的功能若用多个装饰类进行装饰,则会增加该实现类的耦合度。
应用场景
扩展一个类的功能或给一个类添加附加职责。
源码中的应用
# JDK
FilterInputStream
#Servlet Api:
javax.servlet.http.HttpServletRequestWrapper
javax.servlet.http.HttpServletResponseWrapper
FilterInputStream IO源码分析
IO源码结构与装饰模式分析
-
InputStream
:相当于我们装饰模式中类图的Component
; -
FileInputStream
:继承自InputStream
,是具体构建的角色; -
FilterInputStream
:继承自InputStream
,相当于类图中的Decorator
角色, -
DataInputStream
:继承自FilterInputStream
,是具体的修饰角色。
FilterInputStream(装饰类)
public class FilterInputStream extends InputStream {
//持有的被装饰者对象
protected volatile InputStream in;
//初始化的时候就指定被装饰者
protected FilterInputStream(InputStream in) {
this.in = in;
}
//被装饰者方法的调用
public int read() throws IOException {
return in.read();
}
}
DataInputStream(具体的装饰类)
public class DataInputStream extends FilterInputStream implements DataInput {
//构造器:指定被修饰者
public DataInputStream(InputStream in) {
super(in);
}
//扩展的功能,即修饰
public final void readFully(byte b[], int off, int len) throws IOException {
if (len < 0)
throw new IndexOutOfBoundsException();
int n = 0;
while (n < len) {
int count = in.read(b, off + n, len - n);
if (count < 0)
throw new EOFException();
n += count;
}
}
public final char readChar() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (char)((ch1 << 8) + (ch2 << 0));
}
}
方法中的调用
在方法中调用方式和装饰模式调用类似。
DataInputStream dis = new DataInputStream(new FileInputStream("/usr/local/temps/1.txt"));
PS:以上代码提交在 Github :https://github.com/Niuh-Study/niuh-designpatterns.git
文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读, 本文 GitHub org_hejianhui/JavaStudy 已经收录,欢迎 Star。
网友评论