【设计模式系列】结构型之装饰器模式&CosPlay(常用)(上)

219 阅读4分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。

写了几年的学习笔记,现在终于一个学习周期结束了,开始回顾自己学习过的东西,温故知新的同时复盘下自己的笔记,梳理成博客分享出来。这几年其实浪费了挺多时间的,尤其是21年。不得不说,学习是真的苦且反人类,一直驱动着我学习的无非是对35岁的“焦虑”+对编程一点点的喜欢+对“好”代码的好奇心和憧憬。

我并不身处大厂,也不知大厂的代码是不是想象中那么“完美”。但我知道,我只要不停的追求代码的“完美”,怀着对技术的好奇,我就能一直去探索,那我就不会离的太远·······

代码不是凭一点就能断定好坏的,所以我系统学习了设计模式,从无法理解到推崇,因为我看到了这个代码基建界的瑰宝-设计模式的优雅之处。情怀不必多言,搞的跟鸡汤一样。今天,我来聊聊装饰器模式。

正文

先用最简单的代码讲解下什么是装饰器模式,然后再分析下JDK中的InputStream相关的流是如何使用装饰器模式的(JDK中各种流的实现是装饰器模式经典实现,同时还带有了一点定制的感觉)。

下面先看看装饰器模式的定义,这个模式从名字就能猜出一点东西的。

装饰器模式(Decorator Pattern),向现有对象添加新的功能,同时又不会和原有对象产生耦合。

大家不知道对cos是不是有兴趣,今天让大家过过瘾,我们举个cos的例子。来了,上图~

/**
 * 美女
 */
public abstract class Beauty {
    public abstract void wearClothes();
}

/**
 * 护士美女
 */
public class NurseBeauty extends Beauty {
    private final Beauty beauty;

    public NurseBeauty(Beauty beauty) {
        this.beauty = beauty;
    }

    @Override
    public void wearClothes() {
        System.out.println("穿上护士制服");
        beauty.wearClothes();
    }
}

/**
 * 教师制服美女
 */
public class TeacherBeauty extends Beauty {
    private String name;

    public TeacherBeauty(String name) {
        this.name = name;
    }

    @Override
    public void wearClothes() {
        System.out.println("这是名为" + name + "的美女,她穿着教师制服");
    }
}

/**
 * 西装黑丝美女
 */
public class SuitAndBlackSilkBeauty extends Beauty {
    private final Beauty beauty;

    public SuitAndBlackSilkBeauty(Beauty beauty) {
        this.beauty = beauty;
    }

    @Override
    public void wearClothes() {
        System.out.println("穿上西装黑丝");
        beauty.wearClothes();
    }
}

上面有三种类型的美女,她们各有特色,有东方美人的柔情,有西方美女的灵动。。。。扯远了。

她们可以穿各种不同的制服(这就是功能的增强),护士姐姐可以穿上西装黑丝,然后在套上老师的西装外套,想一想~话不多说,让我们看看最后的效果吧!

public class Test {
    public static void main(String[] args) {
        // 1.原始教师美女
        Beauty beauty = new TeacherBeauty("颜如玉");
        // 2.穿上黑丝的教师美女
        Beauty suitAndBlackSilkBeauty = new SuitAndBlackSilkBeauty(beauty);
        // 3.穿上护士服的黑丝教师美女
        Beauty nurseBeauty = new NurseBeauty(suitAndBlackSilkBeauty);
        nurseBeauty.wearClothes();
    }
}

图来~~~~

运行结果.png

上面的美女是很漂亮,但是我们身为程序员,要注重的是内在,透过表象看本质,我们来分析下上面的所有代码,Beauty类作为父抽象类,其他不同类型的美女类都实现Beauty类,同时给自己加上‘新功能’,像黑丝美女她就有穿黑丝的‘新功能’。

总结下上面代码的一些特性

1.所有装饰器类(黑丝美女,护士美女)和原始类(教师美女)继承同一个父类(Beauty类)。这样的好处就是不同的装饰器类可以多个叠加嵌套装饰(既是黑丝美女又是护士美女)。
2.修饰器类是对原有功能的增强而非覆盖,这其实是设计思想上的,你硬说非要弄个完全毫无关系的功能也是可以的,代码可以实现,但是这就不存粹了。
3.各个装饰器互相协助是通过组合这种低耦合的方式而非硬性继承,注意这里说的是各个装饰器之间协作,不是装饰器实现的底层接口(类)。

回顾

装饰器模式主要是适合用于那种扩展功能很多的业务场景(可以只发短信,也可以发短信的同时发邮件,也可以发短信和邮件的同时打电话),一般这种场景我们都会存在多层级的继承关系,为了避免继承关系后期的指数性增长和代码的难扩展性,所以我们使用“组合”的方式解耦各个增强的功能点。还有一点就是装饰器模式是对原有功能的增强(像上面说的场景其实就是对通知功能的一种增强)。

求波关注,公众号:java精进天路

有任何问题都可留言哦!