装饰模式-扩展系统功能

news2024/11/24 21:06:13

 买了新车后,不少人会对车进行装饰,比如给车贴膜,喷上骚粉的漆等。某天,小李和小张都买了辆车,小李想给车贴膜,小张想给车先喷漆然后再贴膜。现在中的做法是,把车开到改装店,如果要喷漆,师傅就给车喷漆,要贴膜,师傅就给车贴膜。这就是本文要将的装饰模式。

1 装饰模式概述

是一种替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。引入装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。

图 装饰模式结构图

Component: 抽象构件,是具体构件和抽象装饰类的共同父类。它的引入使得客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

ConcreteComponent:具体构件,抽象构件类的子类。用于定义具体的构件对象,装饰器可以给它增加额外的职责(方法)。

Decorator: 抽象装饰类,也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。维护了一个指向抽象构件对象的引入,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

ConcreteDecorator: 具体装饰类,负责向构件添加新的职责。每个具体装饰类都定义了一些新的行为,可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

public interface Appearance {

    void show();

}

public class Car implements Appearance{

    private String name;

    public Car(String name) {
        this.name = name;
    }

    @Override
    public void show() {
        System.out.println(name + ":");
    }
}

public class Decorator implements Appearance{

    private Appearance appearance;

    public void setAppearance(Appearance appearance) {
        this.appearance = appearance;
    }

    @Override
    public void show() {
        appearance.show();
    }
}

public class FilmDecorator extends Decorator{

    @Override
    public void show() {
        super.show();
        attachFilm();
    }

    private void attachFilm() {
        System.out.println("贴上一层保护膜");
    }
}

public class PaintDecorator extends Decorator{

    @Override
    public void show() {
        super.show();
        spray();
    }
    private void spray() {
        System.out.println("喷上骚粉色");
    }
}

public class CarTuningShop {

    public static void main(String[] args) {
        Appearance car1 = new Car("小李的车");
        Appearance car2 = new Car("小张的车");

        Decorator filmDec = new FilmDecorator(); //贴膜
        Decorator paintDec = new PaintDecorator(); //喷漆

        filmDec.setAppearance(car1);
        filmDec.show();
        System.out.println("--------");
        filmDec.setAppearance(car2);
        paintDec.setAppearance(filmDec);
        paintDec.show();
//        运行结果:
//        小李的车:
//        贴上一层保护膜
//        --------
//        小张的车:
//        贴上一层保护膜
//        喷上骚粉色
    }

}

1.1 透明装饰模式

要求客户端完全针对抽象编程,对于客户端而言,具体构件对象和具体装饰对象没有任何区别。

优点:可以让客户端透明地使用装饰之前的对象和装饰之后的对象,无须关心它们的区别。

缺点:设计难度较大,有时用户需要单独调用新增的业务方法或者是抽象装饰器的方法,这样就不得不用具体装饰类来定义装饰之后的对象。

1.2 半透明装饰模式

对于客户端,区分了具体装饰对象和构件对象。因为客户端要单独使用装饰器的业务方法,就用具体的装饰类来定义装饰之后的对象。而具体构建类型还是可以使用抽象构件类型来定义,这种装饰模式即为半透明装饰模式。

优点:给系统代理更多的灵活性,设计及使用相对简单。

缺点:客户端需要有区别地对待具体构件与装饰类,

1.3 注意事项

1)尽量保持装饰类的接口与被装饰类的接口相同。这样,对于客户端而言,可以一致地对待它们。也就是说,在可能的情况下,应该尽量使用透明装饰模式。

2)尽量保持具体构件类ConcreteComponent是一个“轻”类。不要把太多的行为放在具体构件类中,可以通过装饰类对其进行扩展。

3)如果只有一个具体构件类,那么抽象装饰类可以作为该具体构件类的直接子类。

2 优缺点

优点:

  1. 比继承更加灵活,不会导致类的个数急剧增加。
  2. 可以通过一种动态的方式来扩展一个对象的功能。
  3. 可以对一个对象进行多次装饰,使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有代码无须改变,符合开闭原则。

缺点:

  1. 将产生很多小对象,会占用更多的系统资源。
  2. 比继承更容易出错,排错也更困难,需要逐级排查。

3 适用场景

  1. 不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  2. 不能采用继承的方式对系统进行扩展或者继承不利于系统扩展和维护。

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

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

相关文章

统一观测丨使用 Prometheus 监控 Cassandra 数据库最佳实践

作者:元格 本篇内容主要包括四部分:Cassandra 概览介绍、常见关键指标解读、常见告警规则解读、如何通过 Prometheus 建立相应监控体系。 Cassandra 简介 Cassandra 是什么? Apache Cassandra 是一个开源、分布式、去中心化、弹性可伸缩、…

day44-Spring_AOP

0目录 1.2.3 1.Spring_AOP 实体类: Mapper接口: Service和实现类: 测试1: 运行后: 测试2:无此型号时 测试3:库存不足时 解决方案1:事务声明管理器 测试&#xff1a…

【从零开始学习JAVA | 第三十篇】方法引用

前言: 方法引用作为一个重要的知识点,虽然他使用起来很复杂,而且会降低代码的可读性,但是如果用好了方法引用,我们也会获得不错的效率,因此我们在今天将为大家讲解什么是方法引用。 方法引用:…

J-Flash合并多个bin文件

文章目录 1. 前言2. 下载 J-Flash 工具3. 合并3个bin文件3.1 Booloader.bin3.2 APP1.bin3.3 APP2.bin3.4 保存 → 导出合并bin文件3.5 未用到的区域会被填充为 FF 4. 欢迎纠正~ 1. 前言 下面介绍用J-Flash工具合并多个bin文件的方法 2. 下载 J-Flash 工具 在下载Jink驱动的…

excel 生成sql技巧

"update 表名 set 字段名"&A2&" where 字段名"&B2&";"

最小栈,设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

题记: 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶…

交换机和终端设备的基本配置

1 IOS访问 1.1 操作系统 所有终端设备和网络设备都需要有操作系统 (OS)。如图所示,操作系统中直接与计算机硬件交互的部分称为内核。与应用程序和用户连接的部分则称为外壳。用户可以使用命令行界面 (CLI) 或图形用户界面 (GUI) 与外壳交互。 使用 CLI 时&#xf…

欧姆龙以太网模块连接MCGS步骤

你是否曾经遇到过这样的问题:在监控PLC数据时,触摸屏无法与PLC通讯,或者PLC的通讯口被占用了?今天,我要向大家介绍一款神奇的设备——捷米特JM-ETH-CP转以太网模块,它能够即插即用,不占用PLC通讯…

被吹爆的Wi-Fi 6,究竟强在哪?

被吹爆的Wi-Fi 6,究竟强在哪? 伴随IoT技术的成熟及发展,Wi-Fi标准也在不断迭代升级,然而就实际情况来说,依旧有不少人仍在使用旧标准,比如Wi-Fi 4、Wi-Fi 5。其实WiFi的每一次升级除了速率更高,…

SpringCloud+Nacos集成Seata-1.7.0分布式事务

Seata是一个比较成熟的分布式事务工具,非常好用,主流的的一套,网上大多都是1.4版本,以及不完整了,鄙人也是找了好久才找到有个1.7版本的详细教程(放在最后面了,毕竟是别人的技术,这里…

打造高效便捷的采购管理平台,提升企业采购效率

随着企业规模的扩大和供应链的日益复杂,传统的手工采购管理方式已经不能满足企业的需求。采购管理平台的出现为企业提供了一个集中、高效、便捷的采购管理工具。本文将重点探讨采购管理平台的意义与作用,并介绍如何打造一个高效便捷的采购管理平台。 一、…

【干货分享】如何恢复SOLIDWORKS 零件、装配体和工程图模板?

当我们卸载了SOLIDWORKS或者是购买了一台新笔记本电脑或是丢失了一直在使用的模板时,我们可以通过打开过去的零件、装配体和工程图文件来恢复 SOLIDWORKS 模板。 ▷ 零件模板 打开包含所需自定义属性的上一个部件。 保存零件的副本以避免对原始文件进行意外更改。…

机器学习深度学习——线性回归的从零开始实现

虽然现在的深度学习框架几乎可以自动化实现下面的工作,但从零开始实现可以更了解工作原理,方便我们自定义模型、自定义层或自定义损失函数。 import random import torch from d2l import torch as d2l线性回归的从零开始实现 生成数据集读取数据集初始…

【技术】国标GB28181视频监控平台EasyGBS视无法播放,抓包返回ICMP

视频流媒体安防监控国标GB28181平台EasyGBS视频能力丰富,部署灵活,既能作为业务平台使用,也能作为安防监控视频能力层被业务管理平台调用。国标GB28181视频EasyGBS平台可提供流媒体接入、处理、转发等服务,支持内网、公网的安防视…

Ansys Speos | Presets 适合用户的预定义参数集

概述 Speos Presets 参数预置功能允许创建预定义的参数集,并将它们应用于新的或现有的 Speos,从任何 Speos 对象创建预设,例如光源,传感器,材料,仿真等,通过一个*.Preset 的文件定对仿真类型的配…

C++之文件操作

1.C文件操作 C中文件操作头文件:fstream。   文件类型:文件文件和二进制文件。 文件操作三大类:     ofstream 写操作     ifstream 读操作     fstream:读写操作 文件打开方式: 标志说明ios::in只读ios::out只写,文件不存在则…

Spring系列一:spring的安装与使用

文章目录 💞 官方资料🍊Spring5下载🍊文档介绍 💞Spring5🍊内容介绍🍊重要概念 💞快速入门🍊Spring操作演示🍊类加载路径🍊Debug配置🍊Spring容器…

基于Centos 7虚拟机的磁盘操作(添加磁盘、分区、格式分区、挂载)

目录 一、添加硬盘 二、查看新磁盘 三、磁盘分区 3.1新建分区 3.2 格式分区 3.3 挂载分区 3.4 永久挂载新分区 3.5 取消挂载分区 一、添加硬盘 1.在虚拟机处选择编辑虚拟机设置,然后选择添加 2.选择硬盘,然后选择下一步 3.默认即可,下一步…

啤酒节,燃起青岛啤酒们的“热血”

【潮汐商业评论/ 原创】 “这周五晚上我们就出发!三年了,终于可以再去啤酒节畅快淋漓了!”作为啤酒爱好者Joe兴奋道。 随着线下经济的复苏,疫情后的第一个盛夏正在被全国各地的“啤酒狂欢”所点燃。 7月14日晚,随着…

Canal安装部署与测试

文章目录 第一章 Canal概述1.1 简介1.2 工作原理1.2.1 MySQL主备复制原理1.2.2 canal 工作原理 1.3 重要版本更新说明1.4 多语言 第二章 Canal安装部署2.1 准备2.2 canal安装 第三章 Canal和Kafka整合测试注意事项 第一章 Canal概述 Github地址:https://github.com…