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


    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Wukong.java

    public class WuKong extends Role{
        public WuKong() {
            super(150, "孙悟空");
        }
    
        public float calculate() {
            return getAggressivity();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Bajie.java

    public class BaJie extends Role{
        public BaJie() {
            super(80, "猪八戒");
        }
    
        public float calculate() {
            return getAggressivity();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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();
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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());
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.2 效果图

    image-20221120231737061

    3 优点及适用场景

    3.1 优点

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

    3.2 适用场景

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

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

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

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

  • 相关阅读:
    世界杯将至,体育类加密项目迎来春天?
    6. Design A Web Crawler
    Python循环部分学习总结
    [springboot源码分析]-Conditional
    QT 网络编程 服务端 客户端 QTcpServer
    【趣味随笔】农业机器人的种类与发展前景
    Vue使用脚手架(nextTick、Vue封装的过度与动画、vue脚手架配置代理)(九)
    noip游记
    Xshell工具连接本地虚拟机Linux系统
    House of storm
  • 原文地址:https://blog.csdn.net/m0_59792745/article/details/127956549