当前位置: 首页 > news >正文

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

文章目录

  • 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类)
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 当对象的功能要求可以动态添加,也可以再动态地撤销时。

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

相关文章:

  • 智慧城市可视化(一)
  • TCP通讯CS模式之C#设计笔记(十八)
  • Python期末复习题:函数
  • treeSelect树组件设置父节点禁用
  • Vue使用axios进行get请求拼接参数的两种方式
  • STM32存储器组织-STM32存储器映像-嵌入式SRAM-STM32位段-嵌入式闪存-STM32启动配置
  • session共享问题及四种解决方案-前端存储、session的复制 、session粘性、后端存储(Mysql、Redis等)
  • 算法篇-------贪心2
  • Python图像处理笔记
  • 基于51单片机的舞蹈机器人四路步进电机控制仿真
  • 8、如何使用FactoryBean向Spring容器中注册bean?
  • 知识蒸馏 | YOLOv7知识蒸馏实战篇 | 2/2*
  • MySQL纯代码复习(上)
  • [附源码]Python计算机毕业设计白果园网上水果超市
  • 【JVM】java的jvm类加载器和类加载子系统
  • 2019.2.20 c++ 知识梳理
  • C++类的相互关联
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • cookie和session
  • crontab执行失败的多种原因
  • Druid 在有赞的实践
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JavaScript的使用你知道几种?(上)
  • Just for fun——迅速写完快速排序
  • miaov-React 最佳入门
  • mysql 数据库四种事务隔离级别
  • SAP云平台里Global Account和Sub Account的关系
  • springboot_database项目介绍
  • Spring声明式事务管理之一:五大属性分析
  • tensorflow学习笔记3——MNIST应用篇
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 浮动相关
  • 机器学习中为什么要做归一化normalization
  • 让你的分享飞起来——极光推出社会化分享组件
  • 深度学习在携程攻略社区的应用
  • 我与Jetbrains的这些年
  • 详解NodeJs流之一
  • ​flutter 代码混淆
  • ###C语言程序设计-----C语言学习(6)#
  • #ifdef 的技巧用法
  • #pragma data_seg 共享数据区(转)
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (day 12)JavaScript学习笔记(数组3)
  • (ZT)出版业改革:该死的死,该生的生
  • (二)windows配置JDK环境
  • (附源码)ssm高校实验室 毕业设计 800008
  • (未解决)macOS matplotlib 中文是方框
  • (正则)提取页面里的img标签
  • (转)iOS字体
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net Core 中间件验签
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .Net程序帮助文档制作