装饰器模式(Decorator Pattern)

23种设计模式系列目录

23种设计模式之单例模式(Singleton Pattern)

23种设计模式之代理模式(Proxy Pattern)

23种设计模式之适配器模式(Adapter Pattern)

23种设计模式之工厂模式(Factory Pattern)

23种设计模式之抽象工厂模式(Abstract Factory Pattern)

23种设计模式之装饰器模式(Decorator Pattern)

--------------------------------------------------------------------------------------------------------------------------

读完本篇文章将会了解以下问题

1. 装饰器模式定义

2. 装饰器模式代码实现

3. 装饰器模式的优缺点分析

4. 装饰器模式使用场景

--------------------------------------------------------------------------------------------------------------------------

1. 装饰器模式定义

       装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构,是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时又避免了类型体系的快速膨胀。

       目的:避免因为使用继承的方式扩展类功能时导致的子类膨胀问题。

       何时使用:不想因为引入静态特征而增加很多子类的情况。

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

       关键代码:1、Component 类充当抽象角色,不应该具体实现。

                         2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。

       标准类图:

  • Component:统一接口,也是装饰类和被装饰类的基本类型。
  • ConcreteComponent:具体实现类,也是被装饰类。
  • Decorator:装饰类,实现Component接口同时在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。
  • ConcreteDecorator:具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。

2. 装饰器模式代码实现

       举个例子,比如有个人叫刘小白,他可能善良,可能性感,可能会跑,也可能会跳。如果不引入设计模式,我们可能写一个名叫刘小白的类,然后写一个善良的刘小白的类,性感的刘小白的类,会跑的刘小白的类,会跳的刘小白的类,让这四个类继承自刘小白的基类。那么问题来了,我要是想要一个善良又能跑的刘小白呢?再去写一个善良又能跑的刘小白类。如果再多一个“可爱”的属性呢,这得要写多少个类啊。。。所以就需要用到装饰器模式,上类图:

       为什么比上面的标准类图还复杂我们下面再说,People:相当于Component,统一接口,在这里作为一个标记接口

public interface People {
}

Liuxiabai:是个人名,为被装饰类,也没写啥内容

public class Liuxiabai implements People{
}

Decorator:具体装饰类的声明类

public class Decorator implements People{
}

Appearance:外观类,继承自装饰类的抽象类

abstract class Appearance extends Decorator{
    public Liuxiabai liuxiabai;
    public Appearance(Liuxiabai liuxiabai){
        this.liuxiabai = liuxiabai;
    }
}

Behavior:行为类,继承自装饰类的抽象类

abstract class Behavior extends Decorator{
    public Appearance liuxiabai;
    public Behavior(Appearance liuxiabai){
        this.liuxiabai = liuxiabai;
    }
}

GoodLiuxiaobai:善良的刘小白类,具体的装饰类

public class GoodLiuxiaobai extends Appearance{
    public GoodLiuxiaobai(Liuxiabai liuxiabai) {
        super(liuxiabai);
    }
    public void Good(){
        System.out.println("Liuxiaobai is good!");
    }
}

SexyLiuxiaobai:性感的刘小白类,具体的装饰类

public class SexyLiuxiaobai extends Appearance{
    public SexyLiuxiaobai(Liuxiabai liuxiabai) {
        super(liuxiabai);
    }
    public void Sexy(){
        System.out.println("Liuxiaobai is sexy!");
    }
}

JumpLiuxiaobai:能跳的刘小白类,具体的装饰类

public class JumpLiuxiaobai extends Behavior{
    public JumpLiuxiaobai(Appearance liuxiabai) {
        super(liuxiabai);
    }
    public void Jump(){
        System.out.println("Liuxiaobai is Jumping!");
    }
}

RunLiuxiaobai:能跑的刘小白类,具体的装饰类

public class RunLiuxiaobai extends Behavior{
    public RunLiuxiaobai(Appearance liuxiabai) {
        super(liuxiabai);
    }
    public void Run(){
        System.out.println("Liuxiaobai is Running!");
    }
}

       上面写了一大堆乱七八糟的估计大家都懵了,没关系,下面让我们来体验一下装饰器模式的魅力大家就理解了,如果我们只想要一个纯的刘小白,那么我们可以:

new Liuxiabai();

如果想要一个善良的刘小白呢?

new GoodLiuxiaobai(new Liuxiabai());

如果想要一个性感的刘小白呢?

new SexyLiuxiaobai(new Liuxiabai());

如果想要一个能跑又性感的刘小白呢?

new RunLiuxiaobai(new SexyLiuxiaobai(new Liuxiabai()));

为什么上图比标准类图还复杂呢,童鞋们可以看到在Behavior(行为类)里保存的实例对象是Appearance(外观类)的对象:

这是为了产生上面最后那种链式适配的效果,在JDK的InputStream中也是这样的,这个我们下面再说。

3. 装饰器模式的优缺点分析

装饰器模式的优点:

       1、相对于继承,灵活性更强,装饰器将功能切分成一个个独立的装饰器,在运行期间可以根据需要动态添加功能,甚至可以对新功能进行自由组合。

       2、相对于继承,扩展性更强,当有新功能需要添加的时候,只需要添加新的装饰器实现类,然后通过组合的方式添加这个新的装饰器,无需修改已有代码,符合开闭原则。

装饰器模式的缺点:

       1、多层装饰比较复杂(引自菜鸟教程,但我感觉不算是缺点,也没感觉到有多复杂。。。)

4. 装饰器模式使用场景

       1、JDK中IO输入输出流的设计

new BufferedReader(new InputStreamReader(new FileInputStream("c:\\test")));

       2、Servlet API中提供了一个request对象的装饰器模式实现类HttpServletRequsetWrapper,增强了requset对象的功能,有兴趣的同学可以去翻一下源码,这里我就不带大家找啦。

       3、MyBatis的缓存组件,这个具体可以看下我这篇博文:啃下MyBatis源码 - org.apache.ibatis.cache包源码分析

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值