1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

设计模式详解——装饰者模式

前言

在程序开发设计中,有一个特别重要的原则是,类应该对扩展开放,对修改关闭,虽然这一原则听起来很矛盾,但是在一些比较优秀的设计模式中,是完全可以达成这一原则的,比如装饰者模式,它就是这一原则的最佳实践,下面我们来看下它的基本原理和用法,希望能通过这篇内容,引发给位小伙伴对于设计模式的思考。

装饰者模式

装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性地替代方案。

要点

  • 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式;
  • 在我们的设计中,应该允许行为可以被扩展,而无须修改现有代码
  • 组合和委托可用于在运行时动态地加上新的行为
  • 除了继承,装饰者模式也可以让我们扩展行为
  • 装饰者模式意味着一群装饰者类,这些类用来包装具体组件
  • 装饰者类反映出被装饰组件地类型(他们具有相同的类型,都经过接口或继承实现)
  • 装饰者可以在被装饰者地行为前面或者后面加上自己的行为,甚至将被装饰者的行为整体覆盖,从而达到特定目的
  • 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型
  • 装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得复杂。

示例代码

原始对象接口

基类接口,也是包装类最底层的内容(俄罗斯套娃里面第一个被套的那个),也可以理解为包装类中的最小单位,这里我们用形状这个抽象概念作为示例演示。

首先这个抽象接口有一个基本方法,就是draw绘制方法,凡是实现了形状这个接口的所有类都必须实现这个接口。

public interface Shape {
    /**
     * 绘制方法
     */
    void draw();
}
接口实现

这里是接口的实现,不过为了方便理解,各位小伙伴可以把接口的实现当作第一层包装类,这一层包装相当于直接确定了我们形状的基本属性,表明它是一个圆形。

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

同理,这里确定了我们的形状为矩形。

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}
装饰对象抽象

这里相当于做一个通用的包装接口,后续的包装类只需要继承这个抽象类,然后再在其中加入新的行为或属性即可,而不需要重复封装。

public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape){
        this.decoratedShape = decoratedShape;
    }

    public void draw(){
        decoratedShape.draw();
    }
}
装饰者实现

这里就是第一层包装(如果按我们上面的说法应该是第三层,因为我们传递的肯定是shape的实现,而不是抽象接口),这里继承了上面的抽象包装类。

public class RedShapeDecorator extends ShapeDecorator {

    public RedShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        setRedBorder(decoratedShape);
    }

    private void setRedBorder(Shape decoratedShape){
        System.out.println("Border Color: Red");
    }
}

同时引入了一个新的方法setRedBorder,这个方法让我们的形状有了一个新的属性——红色。当然,我们还可以继续封装,我们可以在颜色的基础上给他封装一个尺寸:

public class SizeShapeDecorator extends RedShapeDecorator{

    public SizeShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

    @Override
    public void draw() {
        super.draw();
        setSize(decoratedShape);
    }

    private void setSize(Shape decoratedShape) {
        System.out.println("size: 100");
    }
}
测试代码

这里我们分别创建一个圆形和矩形,指定不同的包装类,并调用他们的draw方法:

	@Test
    public void testDecorator() {
        Shape circle = new Circle();
        ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
        ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
        ShapeDecorator sizeRedRectangle = new SizeShapeDecorator(new Rectangle());
        System.out.println("原始圆形");
        circle.draw();

        System.out.println("===========\n包装的红色圆形");
        redCircle.draw();

        System.out.println("===========\n包装的红色矩形");
        redRectangle.draw(); 
        
        System.out.println("===========\n包装的100红色矩形");
        sizeRedRectangle.draw();
    }

最后运行结果如下:

总结

从示例代码及运行结果我们可以看出来,虽然后续我们不断为原始的形状加入了新的属性,但是我们并没有改变原始代码,而是一层一层地添加不同的包装类,然后让它逐步有了更多的新属性。

这样的操作好处是,我们原有的形状拥有了新的属性,但这些后增加的属性和原始形状之间并没有任何强依赖关系,也没有破坏原因业务逻辑,保证了系统的可扩展性,同时耦合性还很低,这就是装饰者设计模式的魅力。

不知道各位小伙伴是否还记得我们前段时间分享的spring boot源码相关内容,spring boot的源码中就用到了装饰者模式,比如BeanFactory的相关内容,另外我们日常开发过程中用到的Tomcat有好多地方也用到了这种设计模式,最典型的是ServletRequestServletResponse

posted @ 2021-10-15 22:06  云中志  阅读(32)  评论(0编辑  收藏  举报