设计模式之装饰器模式(Decorator)

news2024/10/7 2:38:10

一、装饰器模式介绍

       装饰模式(decorator pattern) 的原始定义是:动态的给一个对象添加一些额外的职责。

       就扩展功能而言,装饰器模式提供了一种比使用子类更加灵活的替代方案。

       在软件设计中,装饰器模式是一种用于替代继承的技术,它通过一种无须定义子类的方式

       给对象动态的增加职责,使用对象之间的关联关系取代类之间的继承关系。

二、装饰器模式原理

       装饰器模式结构类图如下所示:

              

       装饰(Decorator)模式中的角色:

               1)抽象构件(Component)角色 :它是具体构件和抽象装饰类的共同父类,声明了

                     在具体构件中实现的业务方法。它引进了可以使客户端以一致的方式处理未被装

                     饰的对象以及装饰之后的对象,实现客户端的透明操作

               2)具体构件(Concrete  Component)角色 :它是抽象构件类的子类,用于定义具体

                    的构建对象,实现了在抽象构建中声明的方法,装饰类可以给它增加额外的职责

                    (方法)。即被装饰者

               3)抽象装饰(Decorator)角色 :它也是抽象构件类的子类,用于给具体构件增加

                    职责,但是具体职责在其子类中实现。它维护了一个指向抽象构件对象的引用,

                    通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达

                    到装饰的目的。

               4)具体装饰(ConcreteDecorator)角色 : 它是抽象装饰类的子类,负责向构件添加

                     新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中

                     定义的方法,并可以增加新的方法用于扩充对象的行为。   

        装饰者模式中的各个角色用代码表示如下:     

/*******************************************************
 * 抽象构建类(抽象构件),
 * 抽象构建类可以是抽象类,也可以是接口
 *
 *******************************************************/
public abstract class Component {

    //抽象方法
    public abstract void operation();
}

/*******************************************************
 * 具体构建类(被装饰类)
 *
 *******************************************************/
public class ConcreteComponent extends Component{

    @Override
    public void operation() {
        //基础功能实现(复杂功能通过装饰类进行扩展)
    }
}


/*******************************************************
 * 抽象装饰类--装饰者模式的核心
 *
 *******************************************************/
public class Decorator extends Component{

    //维持一个对抽象构件对象的引用
    private Component component;

    //注入一个抽象构件类型的对象
    public Decorator(Component component) {
        this.component = component;
    }


    @Override
    public void operation() {
        //调用原有业务方法(这里并没有真正实施装饰,而是提供了一个统一的接口,将装饰过程交给子类完成)
        component.operation();
    }
}


/*******************************************************
 * 具体装饰类
 *
 *******************************************************/
public class ConcreteDecorator extends Decorator{


    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); //调用原有业务方法
        addedBehavior(); //调用新增业务方法
    }

    //新增业务方法
    public void addedBehavior(){
        //......
    }
}

三、装饰器模式应用示例

       以文件读写器程序为例, 演示一下装饰者模式的使用,该示例主要类如下:

               1)DataLoader:抽象的文件读取接口DataLoader ;抽象构件角色

               2)BaseFileDataLoader:具体组件BaseFileDataLoader,重写组件 DataLoader

                     的读写方法;具体构件角色

               3)DataLoaderDecorator:装饰器DataLoaderDecorator,这里要包含一个引用

                     DataLoader 的对象实例 wrapper,同样是重写 DataLoader 方法,不过这里

                     使用 wrapper 来读写,并不进行扩展;抽象装饰者

               4)EncryptionDataDecorator:读写时有加解密功能的具体装饰器

                    EncryptionDataDecorator,它继承了装饰器 DataLoaderDecorator 重写读写方法;

                    具体装饰者

       该示例的UML类图如下:

               

       该示例具体代码如下:

/**
 * 我们以一个文件读写器程序为例, 演示一下装饰者模式的使用
 *
 * 抽象的文件读取接口DataLoader--抽象构建类
 */
public interface DataLoader {
    //读
    String read();
    //写
    void write(String data);
}



*******************************************************
 * 具体组件,重写方法 -- 具体构建类(被装饰类)
 *
 *******************************************************/
public class BaseFileDataLoader implements DataLoader{

    //读取/写入 的文件路径
    private String filePath;

    public BaseFileDataLoader(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public String read() {

        try {
            String result = FileUtils.readFileToString(new File(filePath), "utf-8");
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void write(String data) {
        try{
            FileUtils.writeStringToFile(new File(filePath), data, "utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




/*******************************************************
 * 抽象装饰者类
 *
 * 
 *******************************************************/
public class DataLoaderDecorator implements DataLoader{

    //抽象构建类的引用
    private DataLoader wrapper;

    public DataLoaderDecorator(DataLoader wrapper) {
        this.wrapper = wrapper;
    }

    @Override
    public String read() {
        return wrapper.read();
    }

    @Override
    public void write(String data) {
        wrapper.write(data);
    }
}




/*******************************************************
 * 具体装饰者类--对读取/写入数据 进行加解密
 * 
 *******************************************************/
public class EncryptionDataDecorator extends DataLoaderDecorator{

    public EncryptionDataDecorator(DataLoader wrapper) {
        super(wrapper);
    }

    //重写 抽象构建类的 读/写 方法
    @Override
    public String read() {
        return decode(super.read());
    }

    @Override
    public void write(String data) {
        super.write(encode(data));
    }


    //加密操作
    private String encode(String data) {
        try {
            Base64.Encoder encoder = Base64.getEncoder();
            byte[] bytes = data.getBytes("UTF-8");
            String result = encoder.encodeToString(bytes);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解密
    private String decode(String data) {

        try {
            Base64.Decoder decoder = Base64.getDecoder();
            String result = new String(decoder.decode(data), "UTF-8");
            return result;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


//测试
public class Test {

    public static void main(String[] args) {

        String info = "name:tom java";
        DataLoaderDecorator decorator = new EncryptionDataDecorator(new BaseFileDataLoader("demo.txt"));
        decorator.write(info);

        String data = decorator.read();
        System.out.println(data);
    }
}

四、装饰器模式总结

1、装饰者模式优点

      1)对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加

      2)可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不

            同的具体装饰类,从而实现不同的行为

      3)可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列

           组合可以创造出很多不同行为的组合,得到更加强大的对象

      4)具体构建类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构建类和

           具体装饰类,原有类库代码无序改变,符合开闭原则

2、装饰者模式缺点

      1)在使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相

           互连接的方式有所不同,而不是它们的类或者属性值不同,大量的小对象的产生势必会

          占用更多的系统资源,在一定程度上影响程序的性能

      2)装饰器模式提供了一种比继承更加灵活、机动的解决方案,但同时也意味着比继承更

           加易于出错,排错也更加困难,对于多次装饰的对象,在调试寻找错误时可能需要逐级

           排查,较为烦琐

      

3、装饰者模式适用场景

      1)快速动态扩展和撤销一个类的功能场景。 比如,有的场景下对 API 接口的安全性要求较

            高,那么就可以使用装饰模式对传输的字符串数据进行压缩或加密。如果安全性要求不

            高,则可以不使用。

      2)不支持继承扩展类的场景。 比如,使用 final 关键字修饰的类,或者系统中存在大量通过

            继承产生的子类。

      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java语法之异常

1.异常的概念以及体系结构 1.1 异常的概念 在生活中人会生病,比如咳嗽流鼻涕,头晕等,程序也一样,比如:数据格式不匹配,网络不通畅,内存报警等.在Java中,我们把程序执行的不正常行为称为异常. 比如: 1. 算数异常 System.out.println(10 / 0); // 执行结果 Exception in thread &…

python导出requirements.txt的几种方法

整理了python导出requirements.txt的几种方法和流程 Condapippipreqs 最近又碰到整理requirements.txt的问题,有好几种命令可以做到这一点,但是之前整理的时候会输出一堆乱七八糟的包,这次挨个试了所有方法,特此记录。我的平台是a…

【本地缓存】Java 中的 4 种本地缓存

目录 1、手写一个简单的本地缓存1.1、封装缓存实体类1.2、创建缓存工具类1.3、测试 2、Guava Cache2.1、Guava Cache 简介2.2、入门案例2.2.1、引入 POM 依赖2.2.2、创建 LoadingCache 缓存 2.3、Guava Cache 的优劣势和适用场景 3、Caffeine3.1、Caffeine 简介3.2、对比 Guava…

elasticsearch ES DBA常用语句

一、 查看集群状态 curl -uelastic 连接串:端口/_cluster/health?pretty 集群健康有三种状态:green,yellow,red green:所有主要分片、复制分片都可用yellow:所有主要分片可用,但不是所有复制分片都可用red:不是所有…

基于SSM的学生信息管理系统【附源码】

​基于SSM的学生信息管理系统(源码L文说明文档) 目录 4 系统设计 4.1界面设计原则 4.2功能结构设计 4.3数据库设计 4.3.1数据库概念设计 4.3.2 数据库物理设计 第5章 系统实现 5.1管理员功能实现 5.1.1班级和课程关…

基于企业现状定制化的数字化转型路径和战略性架构规划

如何从企业现状出发规划数字化转型 随着技术的迅猛发展,全球企业都在加速推进数字化转型,以增强市场竞争力并提升运营效率。数字化转型并不是一个统一的模板,它要求企业结合自身的业务现状、行业环境和技术基础,制定个性化的转型…

通信工程学习:什么是B/S浏览器服务器模式

B/S:浏览器服务器模式 B/S(Browser/Server,浏览器/服务器)模式,又称B/S结构,是Web兴起后的一种网络结构模式。在这种模式中,Web浏览器是客户端最主要的应用软件,系统功能实现的核心部…

分享一个基于.net的学生信息管理系统 C#高校教务管理系统(源码、调试、LW、开题、PPT)

💕💕作者:计算机源码社 💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流&…

计算机毕业设计 智慧物业服务系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

初学Vue(2)

文章目录 监视属性 watch深度监视computed 和 watch 之间的区别 绑定样式(class style)条件渲染列表渲染基本列表key的原理列表过滤列表排序收集表单中的数据 v-model过滤器(Vue3已移除) 监视属性 watch 当被监视的属性变化时&am…

使用frp将树莓派穿透到外网

引言 frp官网 最近买了一块树莓派 zero 2w,想要它可以进行远程访问,所以想到了frp这个方案进行穿透,后期会使用树莓派搭建音乐服务器,本人手机内存有点小,xxxx云音乐太占空间,有兴趣的话可以关注后续。 …

在 window 系统下安装 Ubuntu (虚拟机)

文章目录 零、Ubuntu 和 Vmware workstation 资源一、下载 Ubuntu二、下载 Vmware Workstation Pro三、安装 Vmware Workstation Pro四、创建虚拟机五、配置 Ubuntu 零、Ubuntu 和 Vmware workstation 资源 如果觉得自己下载 Ubuntu 和 Vmware workstation 麻烦,也…

如何在 MySQL 中实现数据压缩

如何在 MySQL 中实现数据压缩 在 MySQL 数据库中,数据压缩可以帮助节省存储空间和提高数据传输效率。本篇文章我就一起来看看关于MySQL数据压缩的相关内容。 一、为什么需要数据压缩 随着数据量的不断增长,数据库的存储空间需求也在不断增加。数据压缩…

【Blender Python】1.概述和基础使用

概述 众所周知,Blender是一款开源免费的3D建模软件(当然不限于3D建模)。在Blender中,可以使用其内置的Python解释器执行Python代码,用于程序化的生成网格以及其他内容。你可以基于此创建Blender插件。 这个系列就是快…

gets和puts

今天我们来学习一组新的函数 gets和puts,它们分别对应的是scanf和printf,但在功能和其它方面有着一些差异 1.gets函数 1.char*gets(char*str); 函数功能:简单来说就像上面的格式一样,给他一个地址(送快递总是要留一个…

Omron/TCP 通信过程

1. 首先 TCP 三次握手 2. 客户端向服务器申请节点地址 客户端向服务器发送一个包含Client Node Address字段的数据包 申请节点地址。由于客户端申请的时候还没有节点地址,因此该字段被置为0x00000000。 3. 服务器向客户端确认收到申请 服务器向客户端发送一个确认…

SQL第12课挑战题

1. 返回customers表中的顾客名称(cust_name)和Orders表中的相关订单号(order_num),并按顾客名称再按订单号对结果进行排序。实际上是尝试两次,一次使用简单的等联结语法,一次使用inner join. 2. 让上一题变得更有用一些…

【算法篇】回溯算法类(2)(笔记)

目录 一、LeetCode 题目 1. 子集II 2. 递增子序列 3. 全排列 4. 全排列 II 5. 重新安排行程 6. N皇后 7. 解数独 二、题目思路整理 一、LeetCode 题目 1. 子集II https://leetcode.cn/problems/subsets-ii/description/https://leetcode.cn/problems/subsets-ii/des…

Spring Cloud Netflix Eureka 注册中心讲解和案例示范

在微服务架构中,服务的发现和注册是至关重要的一环。Netflix Eureka 是一个在云端设计的服务注册与发现系统。它允许各个微服务将自身注册到注册中心,并在需要时发现其他服务,从而实现客户端负载均衡、服务容错以及动态扩展。本文将深入分析 …

【Vue】vue-admin-template项目搭建

准备 node环境 node:v16.12.0npm:8.1.0 vue-element-admin下载 官网:https://panjiachen.github.io/vue-element-admin-site/guide/ 我这边下载的是4.4.0版本的,使用其他版本可能会因为所需要的node和npm版本过低或过高导致异常…