装饰器模式揭秘:我用装饰器给手机集成了ChatGPT

news2024/9/22 3:45:38

在平时的开发过程中,我们经常会遇到需要给一个类增加额外功能的需求,但又不想破坏类的原有结构。这时候,装饰器模式就能大显神威了!接下来,我将带你深入了解装饰器模式的原理、优缺点、适用场景以及如何在实际开发中巧妙运用。相信阅读本文后,你一定会对装饰器模式有更加深入的理解。

一,概述

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在不修改原有类结构的情况下,给一个对象动态添加额外的职责。这种模式的关键在于用组合关系代替继承关系,它基于组合关系创建一个包装对象(即装饰器)来包裹原有对象,并保持原有对象不变,将扩展集成在装饰器对象中。装饰器模式是开闭原则的最佳实践。

通常情况下,为了遵循开闭原则,我们在扩展一个类的功能时,不会直接在原有类基础上进行修改,而是用继承方式将扩展的功能集成在子类中。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果不想在增加很多子类的情况下扩展类,我们可以使用组合关系取代继承关系,它比继承能提供更灵活的扩展。

此外,装饰器对象和原对象一般实现相同的接口,这样做有两个好处。其一,客户端不需要区分装饰器对象和被装饰对象,都以统一的方式访问。其二,让装饰器对象的外层可以再套一层装饰器,实现两个装饰器功能的组合,这意味装饰器之间可以多层嵌套,实现更加复杂的功能组合。
decorator02
装饰器模式主要包含以下角色:

  1. 抽象构件(Component):接口或者抽象类,定义实体的抽象行为,下面的具体构件和装饰器都要实现这个接口。
  2. 具体构件(ConcreteComponent):实体类、被包装类,实现抽象构件,表示被装饰的对象。
  3. 抽象装饰器(Decorator):一般为抽象类,持有抽象构件的引用,并且实现了抽象构件。所有的具体装饰器都要继承该抽象装饰器。
  4. 具体装饰器(ConcreteDecorator):继承自抽象装饰器,每一个新的扩展功能都对应一个具体装饰器,具体装饰器之间可以相互嵌套使用。

优点

  • 动态扩展对象功能:装饰器模式遵循开闭原则,允许在不修改原有类的情况下,给对象动态添加新的功能。
  • 保证接口一致性:装饰器对象使用与被装饰对象相同的接口,保证接口一致性,让客户端调用更加简洁。
  • 细粒度的功能控制:装饰器模式允许以细粒度的方式控制对象的功能。可以根据需要选择添加不同的装饰器,组合出满足特定需求的功能组合,而不需要为每个功能组合创建独立的子类。
  • 支持装饰器的嵌套组合:装饰器模式支持嵌套使用多个装饰器,并按照一定顺序进行组合,以实现更复杂的功能扩展。通过嵌套组合,可以灵活地构建出满足特定需求的功能组合。

缺点

  • 增加了复杂性:引入装饰器模式会增加额外的类和对象,增加了系统的复杂性。如果过度使用装饰器模式,可能会导致装饰器的层级过深,代码难以理解和维护。
  • 可能影响性能:每个装饰器都需要包装被装饰对象,并在其上添加额外的功能。这可能会导致对象处理的性能有所降低,尤其是当装饰器的层级较多时。

适用场景

  • 需要在不修改现有对象代码的情况下,动态地扩展其功能。

  • 需要为一个对象提供不同的功能扩展,且这些功能扩展可以实现任意组合。

  • 需要在运行时动态地添加、删除或修改对象的功能。

  • 需要保持接口的一致性,使得客户端代码能够透明地处理被装饰对象和装饰器对象。

  • 当无法或不方便使用继承来扩展对象功能时,装饰器模式提供了一种更灵活的替代方案。

二,实现案例

案例分析

有一家手机生产商,目前生产两种手机,一个是华为手机,一个是小米手机,它们都实现了Phone接口,该接口中定义了一个方法ican,用于展示目前手机的基本功能,包含短信,电话,4G,商城等。现在我们需要扩展两条新的功能,其一为扩展5G功能,其二集成ChatGPT功能。未来我们生产的华为或小米手机可能集成其中一种功能,也可能集成两种功能。对于这样一种场景,我们就非常适合用装饰器模式来实现。

代码实现

步骤1:创建抽象构件和具体构件

public interface Phone {
    void ican();
}
public class HuaWeiPhone implements Phone{
    @Override
    public void ican() {
        System.out.println("huawei capacities:call,sms,4G,huaweiStore");
    }
}
public class XiaoMiPhone implements Phone{
    @Override
    public void ican() {
        System.out.println("xiaomi capacities:call,sms,4G,xiaomiStore");
    }
}

步骤2:创建抽象装饰器,需要实现Phone接口,并且内部包装Phone类型对象。

public abstract class PhoneDecorator implements Phone{
    protected Phone phone;

    public PhoneDecorator(Phone phone) {
        this.phone = phone;
    }
    public void ican(){
        phone.ican();
    }

}

步骤3:创建具体装饰器----5G装饰器

public class Phone5GDecorator extends PhoneDecorator {

    public Phone5GDecorator(Phone phone) {
        super(phone);
    }

    private void add5G() {
        System.out.println("extended capacity: 5G");
    }

    @Override
    public void ican() {
        phone.ican();
        add5G();
    }
}

步骤4:创建具体装饰器----Ai装饰器

public class PhoneAiDecorator extends PhoneDecorator{

    public PhoneAiDecorator(Phone phone) {
        super(phone);
    }
    private void addAi() {
        System.out.println("extended capacity: chatGPT");
    }

    @Override
    public void ican() {
        phone.ican();
        addAi();
    }
}

步骤5:客户端测试

public class Client {
    public static void main(String[] args) {
        //以华为手机为例进行功能扩展
        System.out.println("华为手机:");
        Phone huawei=new HuaWeiPhone();
        huawei.ican();
        System.out.println();

        System.out.println("华为5G手机:");
        PhoneDecorator huawei5G=new Phone5GDecorator(new HuaWeiPhone());
        huawei5G.ican();
        System.out.println();

        System.out.println("集成ChatGPT的华为5G手机:");
        PhoneDecorator huaWeiAi=new PhoneAiDecorator(huawei5G);
        huaWeiAi.ican();
    }
}

测试结果
image-20230531111937128

三,总结

本文详细介绍了装饰器模式的原理和应用,并通过模拟手机功能扩展的案例来帮助大家深入理解装饰器模式。这是一种非常实用的设计模式,它通过组合而非继承的方式,给原有类动态地添加新功能。组合可以让类的扩展更加灵活多变,同时避免继承带来的子类膨胀问题。希望大家在今后实际开发中更好地发现和运用装饰器模式,并能够举一反三,让你的代码更加的优雅。

感谢您的阅读,希望本文能对你有所帮助,如果你喜欢这篇文章,别忘了点赞和关注哦!

1711edbd2bd444b1b647e09c2c3aff0d

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

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

相关文章

无法找到docker.sock

os环境:麒麟v10(申威) 问题描述: systemctl start docker 然后无法使用docker [rootnode2 ~]# systemctl restart docker [rootnode2 ~]# docker ps Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon r…

4、应用层https27

https协议加密流程:使用ssl加密。 一、HTTPS协议 对HTTP协议进行加密后的一个新的协议。 1、加密概念 单说数据加密过去狭义,更多的是防止数据被监听劫持。 加密包含俩个方面:身份验证,加密传输。 1.1身份验证 验证对端的身…

四、传播

文章目录 1、草药迷阵问题2、时序回溯搜索3、传播搜索THE END 1、草药迷阵问题 \qquad 有一个10*10的百草药柜,每一个抽屉里都有5种不同属性的草药,依次打开抽屉来长出草药迷阵,要求寻找一种神奇的药方,满足: 横行&am…

数据结构——C++无锁队列

数据结构——C无锁队列 贺志国 2023.7.11 上一篇博客给出了最简单的C数据结构——堆栈的几种无锁实现方法。队列的挑战与栈的有些不同,因为Push()和Pop()函数在队列中操作的不是同一个地方。因此同步的需求就不一样。需要保证对一端的修改是正确的,且对…

(中等)LeetCode 3. 无重复字符到的最长子串 Java

滑动窗口 以示例一为例,找出从每一个字符开始的,不包含重复字符的最长子串,那么,其中最长的那个字符串即为答案。 当我们一次递增地枚举子串的起始位置,会发现子串的结束位置也是递增的,原因在于&#xf…

Django项目创建

Django项目创建 文章目录 Django项目创建👨‍🏫方式一:终端命令行方式👨‍🔬方式二:Pycharm创建 👨‍🏫方式一:终端命令行方式 1️⃣cmd打开终端,切换到指定目…

WebSell管理工具--中国蚁剑安装教程以及初始化

简介:中国蚁剑是一款开源的跨平台WebShell网站管理工具 蚁剑的下载安装: GitHub项目地址:https://github.com/AntSwordProject/ Windows下载安装: 百度网盘下载链接:链接:https://pan.baidu.com/s/1A5wK…

超细整理,性能测试-性能指标监控命令详细实战,一篇速通

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 性能监控命令&…

自动驾驶代客泊车AVP摄像头与ECU交互需求规范

目录 1 文档范围及控制方法... 5 1.1 目的.... 5 1.2 文档授权... 5 1.3 文档变更管理... 5 1.4 缩写.... 5 1.5 术语.... 5 2 系统组成... 6 2.1 系统框图... 6 2.2 电源供应和时序要求... 7 2.2.1 摄像头供电控制... 7 2.2.2 摄像头上电时序要求…

论文(3)——使用ChatGPT快速提高科研能力!!如何快速构建代码?怎么提高自己的科研能力?如何提高自己的生产力?

文章目录 引言问题描述问题解决智能开发软件的方法ChatGPT Plus 代码解释器使用ChatGPT插件功能 代码工具Coplit学生优惠免费申请Coplit和pycharm的结合 NewBing的申请 总结参考引用 引言 chatGPT大模型用于问问题和debug,NewBing用于搜索论文,cpolit用…

简述HashMap的扩容机制

注意:本博客需要对HashMap源码有过一定理解,看过源码比较好,仅供互相学习参考 JDK1.7和JDK1.8对比 1.7版本: (1). 首先生成一个新数组(2). 遍历老数组每个位置中的链表元素(3). 取每个元素的key,重新计算每个元素在…

深度学习ai学习方向如何规划,算法竞赛,机器学习,搭建环境等答疑

目录 1了解人工智能的背景知识 2 补充数学或编程知识 3 熟悉机器学习工具库 4 系统的学习人工智能 5 动手去做一些AI应用 1了解人工智能的背景知识 一些虽然存在但是在研究或者工业上不常用的知识,为自己腾出更多的时间来去学习,研究。 人工智能里…

2023.7.16-约数的枚举

功能&#xff1a;输入一个整数&#xff0c;结果打印出这个整数所有的约数。 程序&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int a0, b;printf("请输入一个整数&#xff1a;");scanf("%d",&a);printf(&qu…

迭代器模式:相比直接遍历集合数据,使用迭代器有哪些优势?

今天&#xff0c;我们学习另外一种行为型设计模式&#xff0c;迭代器模式。它用来遍历集合对象。不过&#xff0c;很多编程语言都将迭代器作为一个基础的类库&#xff0c;直接提供出来了。在平时开发中&#xff0c;特别是业务开发&#xff0c;我们直接使用即可&#xff0c;很少…

前端基础:HTML和CSS简介

目录 1、HTML 简介 &#xff08;1&#xff09;在 HTML 中引入外部 CSS &#xff08;2&#xff09;在 HTML 中引入外部 JavaScript 2、CSS 简介 &#xff08;1&#xff09;CSS 的基本语法 &#xff08;2&#xff09;三种使用 CSS 的方法 2.1 - 外部 CSS 的使用 2.2 - 内…

Redis简介与安装

文章目录 前言一、Redis简介1. Redis是什么2. Redis的特点3. 数据库类型4. Redis 应用场景 二、Redis下载与安装1. Redis安装包下载地址2. 在 windows系统安装 Redis3. 在Linux系统安装Redis 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客…

面向对象习题

创建类Calc,定义2个数属性以及一个符号属性,编写4个方法add、minus、multiply、divide,4个方法分别进行2个小数的加、减、乘、除运算.在主函数里面接受用户输入2个运算数、1个运算符,根据该运算符选择应该调用哪一个方法进行运算。 定义10名学生&#xff0c;循环接收10名学员的…

【Kubernetes运维篇】RBAC认证授权详解(二)

文章目录 一、RBAC认证授权策略1、Role角色2、ClusterRole集群角色3、RoleBinding角色绑定和ClusterRoleBinding集群角色绑定 二、通过API接口授权访问K8S资源三、案例&#xff1a;常见授权策略1、常见的角色授权策略案例2、常见的角色绑定案例3、常见的ServiceAccount授权绑定…

WIN10更改代理设置后无法保存的解决办法

每次更改代理之后保存&#xff0c;推出界面再进来发现还是和原来一样 这应该是代理报错失败解决办法如下 winR&#xff0c;regedit&#xff0c;打开注册表编辑器 找到计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings里面的Pr…

一例flash打包的文件夹病毒的分析

今天分析一例样本&#xff0c;该样本使用flask编写&#xff0c;使用MDM Zinc3打包成exe&#xff0c;使用文件夹图标&#xff0c;会在系统中除了C盘外所有驱动器根目录创建photo目录&#xff0c;将自身拷贝进去&#xff0c;诱导用户点击&#xff0c;会添加开机启动项&#xff0c…