设计模式系列 — 装饰模式

2020-10-24  本文已影响0人  一角钱技术

点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。
本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。

前言

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源码结构与装饰模式分析

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:以上代码提交在 Githubhttps://github.com/Niuh-Study/niuh-designpatterns.git

文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读, 本文 GitHub org_hejianhui/JavaStudy 已经收录,欢迎 Star。

上一篇 下一篇

猜你喜欢

热点阅读