【设计模式】装饰者模式:以造梦西游的例子讲解一下装饰者模式,这也是你的童年吗?

news2024/12/29 13:12:04

文章目录

  • 1 概述
    • 1.1 问题
    • 1.2 定义
    • 1.3 结构
    • 1.4 类图
  • 2 例子
    • 2.1 代码
    • 2.2 效果图
  • 3 优点及适用场景
    • 3.1 优点
    • 3.2 适用场景

1 概述

1.1 问题

众所周知,造梦西游3有四个角色,也就是师徒四人,这师徒四人每个人都有自己专属的武器和装备。假定我们以及设计出来了Role(角色类),并通过继承的方式创造出来了师徒四人的角色(这里只写两个)。

image-20221120232302990

那么这时候问题来了,如果给角色增加一个武器,该怎么实现呢》

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmLn58Qi-1668959273768)(https://gitee.com/you-tanzhi/pic/raw/master/u=846442474,698297682&fm=253&fmt=auto&app=138&f=JPEG)]

我想你头脑中第一印象会想到继承

如下,创建两个武器九尺钉耙和金箍棒

在这里插入图片描述

image-20221120232824246

这样九尺钉耙和金箍棒就和角色联系起来了,这时候你可以很清晰的发现,如果在增加一个武器,如月牙弓,你就需要分别创建两个子类。如果再增加一个新角色,如沙僧的话,又要增加更多的子类,这实在是太麻烦。就在你疑惑不解,大骂恶心的时候,我们本篇文章的主角装饰者模式闪亮登场了。

1.2 定义

装饰者模式:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。

1.3 结构

装饰者模式有四个角色:

  • 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  • 具体构建角色(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  • 抽象装饰(Decorator)角色:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构建的功能。
  • 具体装饰角色(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

1.4 类图

image-20221120234046978

2 例子

2.1 代码

Role.java

public abstract class Role {
    /* 攻击力 */
    private float aggressivity;
    /* 描述 */
    private String explain;
    /* 计算攻击力的方法 */
    public abstract float calculate();

    public Role(float aggressivity, String explain) {
        this.aggressivity = aggressivity;
        this.explain = explain;
    }

    public float getAggressivity() {
        return aggressivity;
    }

    public void setAggressivity(float aggressivity) {
        this.aggressivity = aggressivity;
    }

    public String getExplain() {
        return explain;
    }

    public void setExplain(String explain) {
        this.explain = explain;
    }
}

Equipment.java

public abstract class Equipment extends Role{
    /* 角色的变量 */
     Role role;

    public Equipment(float aggressivity, String explain, Role role) {
        super(aggressivity, explain);
        this.role = role;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}

Wukong.java

public class WuKong extends Role{
    public WuKong() {
        super(150, "孙悟空");
    }

    public float calculate() {
        return getAggressivity();
    }
}

Bajie.java

public class BaJie extends Role{
    public BaJie() {
        super(80, "猪八戒");
    }

    public float calculate() {
        return getAggressivity();
    }
}

GoldHoopRod.java

public class GoldHoopRod extends Equipment{
    public GoldHoopRod(Role role) {
        super(90, "金箍棒", role);
    }

    public float calculate() {

        return getAggressivity()+role.calculate();
    }


    public String getExplain() {
        return super.getExplain()+role.getExplain();
    }
}

NineToothRake.java

public class NineToothRake extends Equipment{
    public NineToothRake(Role role) {
        super(60, "九尺钉耙", role);
    }

    public float calculate() {

        return getAggressivity()+role.calculate();
    }


    public String getExplain() {
        return super.getExplain()+role.getExplain();
    }
}


Player.java

package com.you.Demo19;

public class Player {
    public static void main(String[] args) {
        Role role = new WuKong();
        System.out.println("原始的角色:"+role.getExplain()+"  的战斗力  "+role.getAggressivity());
        System.out.println("---------------------------");
        /* 猴哥拿起金箍棒的战斗力 */
        role = new GoldHoopRod(role);
        System.out.println(role.getExplain()+"  "+role.calculate());
        /* 猴哥拿起九尺钉耙+金箍棒的战斗力 */
        role = new NineToothRake(role);
        System.out.println("---------------------------");
        System.out.println(role.getExplain()+" "+role.calculate());
        /* 猪八戒拿起支持钉耙~战斗力 */
        System.out.println("----------------------------");
        Role role1 = new BaJie();
        role1 = new NineToothRake(role1);
        System.out.println(role1.getExplain()+"   "+role1.calculate());


    }
}

2.2 效果图

image-20221120231737061

3 优点及适用场景

3.1 优点

  • 装饰者模式可以带来比继承更具灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果,装饰者模式比继承更具良好的扩展性,完美的遵循开闭原则,继承是静态的附加责任,装饰者是动态的附加责任。
  • 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态拓展一个实现类的功能。

3.2 适用场景

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时(主要有两类)
    • 第一类是系统中存在大量独立的拓展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;
    • 第二类是因为类定义不能继承(如Final类)
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 当对象的功能要求可以动态添加,也可以再动态地撤销时。

在本例子中,指的就是把装备类删掉,并不影响原有的代码。

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时(主要有两类)
    • 第一类是系统中存在大量独立的拓展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;
    • 第二类是因为类定义不能继承(如Final类)
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 当对象的功能要求可以动态添加,也可以再动态地撤销时。

在本例子中,指的就是把装备类删掉,并不影响原有的代码。

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

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

相关文章

推荐10个Vue 3.0开发的开源前端项目

Vue 是一款用于构建用户界面的 JavaScript 框,它基于标准 的HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,用以帮助开发者高效地开发用户界面。目前,Vue 3.0正式版也发布了两年的时间,越累越多的开发者也用上了Vue 3.0。 对比Vue2.x,Vue 3.0在…

并发bug之源(二)-有序性

什么是有序性? 简单来说,假设你写了下面的程序: java int a 1; int b 2; System.out.println(a); System.out.println(b);但经过编译器/CPU优化(指令重排序,和编程语言无关)后可能就变成了这样&#x…

【DDR3 控制器设计】(7)DDR3 的用户端口读写模块设计

写在前面 本系列为 DDR3 控制器设计总结,此系列包含 DDR3 控制器相关设计:认识 MIG、初始化、读写操作、FIFO 接口等。通过此系列的学习可以加深对 DDR3 读写时序的理解以及 FIFO 接口设计等,附上汇总博客直达链接。 【DDR3 控制器设计】系列…

CSS---复合选择器

目录 一:复合选择器的介绍 二、复合选择器的讲解 (1)后代选择器 (2)子元素选择器 (3)并集选择器 (4)链接伪类选择器 (5)focus伪类选择器 一&…

基于SpringBoot的线上买菜系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SpringBoot 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目…

【Spring系列】- Spring事务底层原理

Spring事务底层原理 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 一个有梦有戏的人 怒放吧德德 🌝分享学习心得,欢迎指正&#xff0…

Vue-CLI的安装、使用及环境配置(超详细)

Vue CLI 是一个基于 Vue 进行快速项目开发的工具。它可以提供可交互式的项目脚手架和运行时的服务依赖,帮助你快速完成一个风格统一、拓展性强的现代化 web 单页面应用。 Vue-CLI 所需环境 Vue-CLI 是一个需要全局安装的NPM包,安装需要在 Node.js 环境下…

一、openCV+TensorFlow环境搭建

目录一、anaconda安装二、tensorflow安装三、Opencv安装四、pycharm新建项目使用Anaconda的环境五、验证环境安装六、tensorflow安装jupyter notebook一、anaconda安装 anaconda官网:https://www.anaconda.com/anaconda下载:https://repo.anaconda.com/…

【k8s】10.网络插件

文章目录一、etcd详解1、etcd的特点2、准备签发证书的环境二、网络插件原理1、flannel1.1 UDP模式(性能差)1.2 VXLAN模式(性能较好)1.3 host-gw模式(性能最高)2、calico插件3、总结一、etcd详解 etcd是Cor…

Redis_第二章_实战篇_第一节_ 短信登录

Redis_第二章_实战篇_第一节_ 短信登录 文章目录Redis_第二章_实战篇_第一节_ 短信登录短信登录1.1、导入黑马点评项目1.1.1 、导入SQL1.1.2、有关当前模型1.1.3、导入后端项目1.1.4、导入前端工程1.1.5 运行前端项目:1.2 、基于Session实现登录流程1.3 、实现发送短信验证码功…

ANDI数据集介绍|补充信息|2022数维杯国际赛C题

目录 1.患者基本信息 2.生物标记物量化值 3.认知评估 4.解剖结构量化值 5.Other 6.上述各信息的bl值 1.患者基本信息 RID (Participant roster ID) ex. 2、PTID (Original study protocol) ex. 011_S_0002、VISCODE (Visit code) ex. bl、SITE ex. 11、COLPROT (Study p…

服务拆分和远程调用(微服务)

博客主页:踏风彡的博客 博主介绍:一枚在学习的大学生,希望在这里和各位一起学习。 所属专栏:SpringCloud 文章创作不易,期待各位朋友的互动,有什么学习问题都可在评论区留言或者私信我,我会尽我…

课程设计 | 教学设备管理系统

🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! &…

SpringCloud微服务(二)——Eureka服务注册中心

Eureka服务注册中心 SpringCloud组件,Eureka已停更。 内容简介 1、Eureka是什么 Eureka 是 Netflix 开发的,一个基于 REST 服务的,服务注册与发现的组件,以实现中间层服务器的负载平衡和故障转移。服务注册:将服务…

[杂记]算法: 单调栈

0. 引言 单调栈, 顾名思义就是从栈底到栈顶元素单调递增或者单调递减的栈. 往往, 我们在解决寻找一个元素前面/后面的最远/最近处满足某条件的另一个元素的时候可以用到单调栈. 也是用两道算法题作为例子. 在这之前, 先简单写一下构造单调栈的模板. 如果我们需要从一个数组中…

ES6 入门教程 18 Iterator 和 for...of 循环 18.7 for...of 循环

ES6 入门教程 ECMAScript 6 入门 作者:阮一峰 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录ES6 入门教程18 Iterator 和 for...of 循环18.7 for...of 循环18.7.1 数组18.7.2 Set 和 Map 结构18.7.3 计算生成的数据结构18.7.4 类似…

供应叶酸PEG试剂Folic acid-PEG-Azide,FA-PEG-N3,叶酸-聚乙二醇-叠氮

1、名称 英文:Folic acid-PEG-Azide,FA-PEG-N3 中文:叶酸-聚乙二醇-叠氮 2、CAS编号:N/A 3、所属分类:Azide PEG Folic acid(FA) PEG 4、分子量:可定制,FA-PEG-N3 5…

Web安全之CTF测试赛

Web安全之CTF测试赛 1.000-我是谁 题目描述: 找到诈骗网站bsde.cn的域名注册人及邮箱,将域名注册人的126邮箱填写到下方答案框并点击送出 考察点:whois查询 whois查询网址: https://x.threatbook.com/ //微步在线 http://wh…

ES6 入门教程 17 Promise 对象 17.11 Promise.reject() 17.12 应用 17.13 Promise.try()

ES6 入门教程 ECMAScript 6 入门 作者:阮一峰 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录ES6 入门教程17 Promise 对象17.11 Promise.reject()17.12 应用17.12.1 加载图片17.12.2 Generator 函数与 Promise 的结合17.13 Promise…

ES6 入门教程 15 Proxy 15.2 Proxy 实例的方法 15.2.2 set() 15.2.3 apply()

ES6 入门教程 ECMAScript 6 入门 作者:阮一峰 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录ES6 入门教程15 Proxy15.2 Proxy 实例的方法15.2.2 set()15.2.3 apply()15 Proxy 15.2 Proxy 实例的方法 拦截方法的详细介绍。 15.2.…