Live2D

学习记录-装饰器模式

 


装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

补充知识点:什么是方法的签名

方法的签名:由方法的名称形参列表组成,具体来说,一个方法的签名由它的名称以及它的形参的个数修饰符和类型组成。

介绍

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,这种方式是静态的,一定要写一个新的子类,对类层级进行扩展,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。

应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。

注意事项:可代替继承。

实现

例子

image-20230111200437249

现在有一个机器人,它有对话、唱歌、放音乐的功能,但是由于买家的需求,现在需要对机器人功能进行扩展,要求机器人除了原本的功能还需要有拖地、跳舞的功能。

现在有两种解决方案。

第一种方案:在第一代产品的基础上,重新研制第二代产品。即继承机制,就是继承一个现有的类,在子类进行扩展功能。

第二种方案:直接对第一代产品进行升级改造,不再另外生成新一代机器人。即关联机制,把一个类的对象嵌入到另一个类的对象中(我们拿到一个类就可以对其进行扩展,不需要修改原有类逻辑),相对于把机器人嵌入到箱子里来,给他套一个壳子,来扩展功能,那个壳子呢,就是我们所说的装饰器。这种方式呢,也称为装饰器模式。

类图

image-20230111195910349

代码实现

public class Main {
    public static void main(String[] args) {
        //这种书写方式是不是很熟悉,我们在用IO流的经常使用
        //没错,Java的IO流也大量使用了装饰器模式
        new RobotDecorator(new FirstRobot()).doMoreThing();
    }

    /*步骤一
    首先呢,我们定义一个接口,它代表了那些需要被修饰的对象,这个接口我们叫机器人接口
     */
    interface Robot{
        void doSomeThing();
    }

    /*步骤二
    实现第一代机器人
    注:这里static修饰知识因为在main函数里调用了相关函数,并无其它意义。
    */
    static class FirstRobot implements Robot{

        @Override
        public void doSomeThing() {
            System.out.println("对话");
            System.out.println("唱歌");
            System.out.println("放音乐");
        }
    }

    /*步骤三
    定义一个装饰器来对第一代机器人功能扩展,它需要实现和机器人一样的接口。
    即它装饰的那个对象的功能它也要有。
    注:这里static修饰知识因为在main函数里调用了相关函数,并无其它意义。
    */
    /*在这里我们可以定义为抽象类,这样可以定义其子类去实现更多的装饰器(更灵活)*/
    static class RobotDecorator implements Robot{
        /*首先呢,我们需要定义一个字段,因为我们要关联使用机器人,所以我们来定义一个机器人字段*/
        private Robot robot;

        /*接着呢,要传这个对象进来,用构造方法去传*/
        public RobotDecorator(Robot robot){
            this.robot=robot;
        }

        /*接着呢,我们去实现机器人该有的方法*/
        @Override
        public void doSomeThing() {
            /*这里呢,我们直接让机器人去做就行了*/
            robot.doSomeThing();
        }

        /*扩展功能,它可以做原有的功能,也可以做新的功能*/
        public void doMoreThing(){
            robot.doSomeThing();
            System.out.println("跳舞、拖地");
        }
    }
}

运行结果

对话
唱歌
放音乐
跳舞、拖地

此文章参考:

【菜鸟教程】:https://www.runoob.com/design-pattern/decorator-pattern.html

【五分钟学设计模式.05.装饰器模式-哔哩哔哩】: https://b23.tv/zwp3Rob

posted @   都是朕的江山  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
返回顶端
点击右上角即可分享
微信分享提示