美文网首页
设计模式系列 — 装饰模式

设计模式系列 — 装饰模式

作者: 一角钱技术 | 来源:发表于2020-10-24 23:51 被阅读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源码结构与装饰模式分析
  • 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:以上代码提交在 Githubhttps://github.com/Niuh-Study/niuh-designpatterns.git

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

相关文章

  • 设计模式整理(11) 装饰模式

    学习《Android 源码设计模式解析与实践》系列笔记 介绍 装饰模式,也称包装模式,结构型设计模式之一。 定义 ...

  • Android 装饰者模式

    Android 设计模式系列文章 Android 23种设计模式 一、前言 装饰者模式也称为包装模式,其使用一种对...

  • 手撸golang 结构型设计模式 装饰器模式

    手撸golang 结构型设计模式 装饰器模式 缘起 最近复习设计模式拜读谭勇德的<<设计模式就该这样学>>本系列笔...

  • 设计模式系列:装饰模式

    场景 早上饿了,我要煎饼果子。(我也是来了北京之后,知道早点还有煎饼果子,哈哈!)我对师傅说:师傅,来一套煎饼果子...

  • 设计模式系列 — 装饰模式

    点赞再看,养成习惯,公众号搜一搜【一角钱技术[https://p3-juejin.byteimg.com/tos-...

  • Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:《Java设计模式系列-装饰器模式》 一、概述 装饰器模式作用是针对目标方法进行增强,提...

  • 9、结构型模式-装饰器设计模式

    1、如虎添翼的设计模式-装饰器设计模式 简介:讲解-装饰器设计模式介绍和应用场景 装饰器设计模式(Decorato...

  • 安卓设计模式(四)装饰者模式

    本文将讨论Java设计模式中比较重要的模式之一:装饰者模式 该系列其他文章: 安卓设计模式(一)面向对象六大设计原...

  • 设计模式笔记汇总

    目录 设计原则 “依赖倒置”原则 未完待续... 设计模式 设计模式——策略模式 设计模式——装饰者模式 设计模式...

  • 11.4设计模式-装饰模式-讲解

    设计模式-装饰模式 装饰模式详解 装饰模式在android中的实际运用,避免了耦合 1. 装饰模式详解 2.装饰模...

网友评论

      本文标题:设计模式系列 — 装饰模式

      本文链接:https://www.haomeiwen.com/subject/exkgmktx.html