03-JAVA设计模式-装饰模式

装饰模式

什么装饰模式

装饰器模式(Decorator Pattern)也叫包装器模式,是一种结构型设计模式,允许用户在不改变对象的情况下,动态地给对象增加一些额外的职责(功能)。装饰器模式相比生成子类更为灵活,因为可以在运行时根据需要动态地添加或删除功能。

职责

  • 动态的为一个对象增加新的功能
  • 装饰模式是一种用于替代继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

实现细节

  • 抽象组件(Component):定义一个抽象接口,用于规定准备接收附加责任的对象,即可以给这些对象动态地添加职责。
  • 具体组件(ConcreteComponent):实现了抽象组件的接口,定义了一个具体的“被装饰”对象,这个对象可以被装饰器动态地添加功能。
  • 抽象装饰器(Decorator):继承自抽象组件,并持有一个抽象组件的引用。抽象装饰器中声明了与抽象组件相同的方法,并保留了新增功能的接口,以供具体装饰器添加新的功能。
  • 具体装饰器(ConcreteDecorator):实现抽象装饰器所增加的功能,并在调用原有方法时,增加新的功能。

优点

  • 扩展对象功能,比继承灵活,不会导致类个数的急剧增加
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
  • 具体构件类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。

缺点

  • 产生很多小对象。大量小对象占据内存,一定程度上影响性能
  • 装饰器模式容易出错,调试排查比较麻烦

案例

一台普通通话手机,可扩展出具有拍照功能,NCF功能,联网功能

UML

在这里插入图片描述

实现步骤:

  1. 定义一个抽象组件,用于规定准备接收附加功能/职责的方法IPHONE
  2. 定义一个具体组件,实现抽象组件,及实现具备基础功能/职责
  3. 定义一个抽象装饰器,继承抽象组件,并持有一个抽象组件的引用。实现抽象组件接口方法中调用传入接口组件引用的具体实例的方法,达到调用已具备功能/职责
  4. 定义一个/多个具体装饰器,继承抽象装饰器,增加新功能,实现抽象接口时调用原有方法,及新增功能/职责

实现代码

IPhone.java

// 抽象组件:
// *  定义一个手机具备某种功能接口的抽象类
public interface IPhone {
     // 具备功能
     void function();
}

Phone.java

// 具体组件:
// 定义一个具体组件包含最基础的功能:普通手机
public class Phone implements IPhone {
    @Override
    public void function(){
        System.out.println("具备通讯功能");
    };
}

PhoneExtendFunction.java

//抽象装饰器
// 继承自抽象组件,并持有一个抽象组件的引用
public class PhoneExtendFunction implements IPhone{
    // 持有一个抽象组件的引用,调用已具有的功能
    private IPhone phone;

    public PhoneExtendFunction(IPhone phone) {
        this.phone = phone;
    }
    @Override
    public void function() {
        phone.function();
    }
}

InternetFunction.java

// 具体装饰器
// 实现抽象装饰器所增加的功能,并在调用原有方法时,增加新的功能。
public class InternetFunction extends PhoneExtendFunction {
    public InternetFunction(IPhone phone) {
        super(phone);
    }
    public void internet(){
        System.out.println("联网功能");
    }
    @Override
    public void function() {
        super.function();
        internet();
    }
}

NfcFunction.java

// 具体装饰器
// 实现抽象装饰器所增加的功能,并在调用原有方法时,增加新的功能。
public class NfcFunction extends PhoneExtendFunction{
    public NfcFunction(IPhone phone) {
        super(phone);
    }
    public void nfc(){
        System.out.println("NFC功能");
    }
    @Override
    public void function() {
        super.function();
        nfc();
    }
}

PhotographFunction.java

// 具体装饰器
// 实现抽象装饰器所增加的功能,并在调用原有方法时,增加新的功能。
public class PhotographFunction extends PhoneExtendFunction{
    public PhotographFunction(IPhone phone) {
        super(phone);
    }
    public void photograph(){
        System.out.println("摄影功能");
    }
    @Override
    public void function() {
        super.function();
        photograph();
    }
}

TestClient.java

public class TestClient {
    public static void main(String[] args) {
        PhotographFunction phone = new PhotographFunction(new InternetFunction(new NfcFunction(new Phone())));
        phone.function();
    }
}

执行结果:

在这里插入图片描述

装饰器模式和桥接模式的区别

装饰器模式的主要特点是在不改变现有对象结构的情况下,动态地给对象增加一些职责(功能)。装饰器是继承的有力补充,比继承更加灵活。通过使用不同的装饰类和它们的排列组合,可以实现不同的效果。在装饰器模式中,通常会有一个抽象组件和多个具体装饰器,每个装饰器都可以为对象添加新的功能,而且这些装饰器可以灵活地叠加使用。

桥接模式则是将抽象化与实现化分离,使它们可以独立变化。桥接模式包括两个继承体系:抽象部分和实现部分。抽象部分定义了一个接口,规定了实现部分需要实现的方法。实现部分则是具体的实现细节。通过这种方式,桥接模式可以减少派生类的增长,因为你可以将不同的抽象部分和实现部分进行组合,从而得到不同的功能。

两者的主要区别在于:

  • 关注点不同:装饰器模式关注于在不改变对象结构的情况下动态增加功能,而桥接模式关注于将抽象与实现分离,使它们能够独立演化。
  • 结构差异:装饰器模式是通过包装一个已存在的对象,并为其增加新的功能或行为。桥接模式则是通过抽象与实现的分离来组合不同的功能。
  • 行为的叠加性:在装饰器模式中,装饰的行为可以叠加,装饰后的对象可以拥有多个装饰器所添加的功能。而在桥接模式中,行为通常不会叠加,而是通过抽象与实现的组合来提供不同的功能。
  • 稳定性与灵活性:装饰器模式中的对象本身比较稳定,主要是为了增加新功能。而桥接模式本身可能不太稳定,因为实现部分可以独立变化。然而,这也使得桥接模式更加灵活,可以适应更多的变化和需求。

总的来说,装饰器模式和桥接模式在设计和使用上有着明显的区别。装饰器模式更注重在不改变原有结构的基础上增加新功能,而桥接模式更注重抽象与实现的分离和灵活组合

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OSCP靶场--Hetemit

OSCP靶场–Hetemit 考点(python代码注入 systemctrl提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.117 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 05:52 EDT Nmap scan report for 192.168.1…

预训练的启蒙:浅谈BERT、RoBERTa、ALBERT、T5

文章目录 Transformer揭开预训练序幕为什么RNN/LSTM需要从头训练? BERT核心特点预训练任务架构应用和影响 RoBERTa改进点BERT和RoBERTa的MASK策略对比BERT的静态MASK策略RoBERTa的动态MASK策略效果 总结 ALBERT改进点参数共享因式分解嵌入参数和LoRa对比 总结 T5核心…

Chrome谷歌下载入口

​hello,我是小索奇 发现好多人说谷歌浏览器在哪里下载呀,哪里可以找到? 你可能会心想,一个浏览器你还不会下载啊? 还真是,有很多伙伴找不到下载入口,为什么呢? Bing进行搜索&am…

微信小程序转盘抽奖

场景: 在微信小程序里面开展抽奖活动使用转盘抽奖;类似下图(图片来自百度) 方法: 使用lukcy-canvas组件 在 微信小程序 中使用 | 基于 Js / TS / Vue / React / 微信小程序 / uni-app / Taro 的【大转盘 & 九宫…

unipush+个推实现消息推送

1.注册个推平台的帐号个推,专业的数据智能服务商-为垂直领域提供数据智能解决方案 2.应用列表中选择新增应用/服务 3.填写下应用信息4.创建好应用后在manifest.json中的sdkConfigs配置上写入appid、appkey、appsecret "sdkConfigs" : {"ad" :…

hive 数据库表常用操作及相关函数讲解

创建数据库并指定hdfs存储位置 create database myhive2 location ‘/myhive2’; 使用location关键字,可以指定数据库在HDFS的存储路径。 Hive的库在HDFS上就是一个以.db结尾的目录 默认存储在: /user/hive/warehouse内 当你为Hive表指定一个LOCATION时…

二分查找详解

以力扣2529为例,题目要求找到正整数的个数和负整数的个数。 一次遍历数组的方法的时间复杂度为O(n),而二分查找的时间复杂度为O(logn)。 使用二分查找思路:所给nums数组升序排列,找…

基于用户的协同过滤算法实现商品推荐

文章目录 简介基于协同过滤算法(UserCF)原理(我的理解)皮尔逊相关系数计算 总结 简介 最近在做关于健康商城的项目,在首页需要向用户展示食品推荐,要求采用协同过滤的方式展示推荐的食品,第一次…

【Python】FANUC机器人OPC UA通信并记录数据

目录 引言机器人仿真环境准备代码实现1. 导入库2. 设置参数3. 日志配置4. OPC UA通信5. 备份旧CSV文件6. 主函数 总结 引言 OPC UA(Open Platform Communications Unified Architecture)是一种跨平台的、开放的数据交换标准,常用于工业自动化…

Vue - 2( 10000 字 Vue 入门级教程)

一&#xff1a;初识 Vue 1.1 绑定样式 1.1.1 绑定 class 样式 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>绑定样式</title><style>......</style><script type"text/javascript"…

AOF文件重写

1.2.3.AOF文件重写 因为是记录命令&#xff0c;AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作&#xff0c;但只有最后一次写操作才有意义。通过执行bgrewriteaof命令&#xff0c;可以让AOF文件执行重写功能&#xff0c;用最少的命令达到相同效果。 如图&am…

互联网产品经理必备知识详解

1. 前言 本文档全面探讨了产品经理在产品管理过程中的关键环节,包括市场调研、产品定义及设计、项目管理、产品宣介、产品市场以及产品生命周期。通过深入剖析这些方面,本文旨在帮助产品经理系统地理解和掌握产品管理的核心要素,从而提升产品开发的效率和成功率。在市场调研…

分布式锁-redission

5、分布式锁-redission 5.1 分布式锁-redission功能介绍 基于setnx实现的分布式锁存在下面的问题&#xff1a; 重入问题&#xff1a;重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中&#xff0c;可重入锁的意义在于防止死锁&#xff0c;比如HashTable这样的代码…

多维 HighCharts

1&#xff1a;showHighChart.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><!-- js脚本都是官方的,后两个是highchart脚本 --><script type"text/javascript" src"jquery1.7.1.mi…

Unity 九宫格

1. 把图片拖拽进资源文件夹 2.选中图片&#xff0c;然后设置图片 3.设置九宫格 4.使用图片&#xff0c;在界面上创建2个相同的Image,然后使用图片&#xff0c;修改Image Type 为Sliced

书生·浦语大模型第二期实战营第二课笔记和基础作业

来源&#xff1a; 作业要求:Homework - Demo 文档教程:轻松玩转书生浦语大模型趣味 Demo B站教程:轻松玩转书生浦语大模型趣味 Demo 1. 笔记 2.基础作业 2.1 作业要求 2.2 算力平台 2.3 新建demo目录&#xff0c;以及新建目录下的文件&#xff0c;下载模型参数 2.4 Intern…

怎样系统地学习自动化测试?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 平时的测试工作其实细分一下&#xff0c;大概有三个领域…

【面试题】redis在工作中的使用场景有哪些?

前言&#xff1a;在实际工作中&#xff0c;Redis作为一种高性能的内存数据库和缓存系统&#xff0c;可以应用于多种场景&#xff0c;同时在面试过程中也经常被问到类似的问题&#xff0c;我们经常会被问的一脸懵逼&#xff0c;那今天我们就来总结一下redis的一些使用场景。 数据…

Linux--进程间的通信-匿名管道

进程间的通信 进程间通信&#xff08;IPC&#xff0c;Interprocess Communication&#xff09;是指在不同进程之间传输数据和交换信息的一种机制。它允许多个进程在同一操作系统中同时运行&#xff0c;并实现彼此之间的协作。 进程间通信方式&#xff1a; 管道&#xff08;Pi…

应该如何进行POC测试?—【DBA从入门到实践】第三期

在数据库选型过程中&#xff0c;为确保能够灵活应对数据规模的不断扩大和处理需求的日益复杂化&#xff0c;企业和技术人员会借助POC测试来评估不同数据库系统的性能。在测试过程中&#xff0c;性能、并发处理能力、存储成本以及高可用性等核心要素通常会成为大家关注的焦点&am…