设计模式之装饰器模式

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

什么是装饰器模式

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

网络异常,图片无法展示
|

  • Component为统一接口,也是装饰类和被装饰类的基本类型。
  • ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
  • Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
  • ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。

代码实现装饰器模式

抽象构件

public abstract class Component{
    // 抽象地方法
    public abstract void cost();
}

具体基础构件

public class ConcreteComponent extends Component{
    @Override
    public void cost(){
        // do something ...
    }
}

抽象装饰角色:

public abstract class Decorator extends Component{
    private Component component = null;
    public Decorator(Component component){
        this.component = component;
    }
    @Override
    public void cost(){
        this.component.cost();
    }
}

具体装饰角色:

public class ConcreteDecorator extends Decorator{
    public ConcreteDecorator(Component component){
        super(component);
    }
    // 定义自己的修饰逻辑
    private void decorateMethod(){
        // do somethind ... 
    }
    // 重写父类的方法
    public void cost(){
        this.decorateMethod();
        super.cost();
    }
}

优缺点

优点:

  • 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
  • 装饰器模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component(因为Decorator本身就是继承自Component的),实现的还是is-a的关系。
  • 装饰模式可以动态地扩展一个实现类的功能,比如在I/O系统中,我们直接给BufferedInputStream的构造器直接传一个InputStream就可以轻松构件一个带缓冲的输入流,如果需要扩展,我们继续“装饰”即可。

缺点:

  • 多层的装饰是比较复杂的。为什么会复杂?你想想看,就像剥洋葱一样,你剥到最后才发现是最里层的装饰出现了问题,可以想象一下工作量。这点从我使用Java I/O的类库就深有感受,我只需要单一结果的流,结果却往往需要创建多个对象,一层套一层,对于初学者来说容易让人迷惑。

总结

    一个设计模式的出现一定有他特殊的价值。仅仅看见上面的结构图你可能会想,为何要兜这么一圈来实现?仅仅是想要多一行输出,我直接继承ConcretComponent,或者直接在另一个Component的实现类中实现不是一样吗?

    首先,装饰器的价值在于装饰,他并不影响被装饰类本身的核心功能。在一个继承的体系中,子类通常是互斥的。比如一辆车,品牌只能要么是奥迪、要么是宝马,不可能同时属于奥迪和宝马,而品牌也是一辆车本身的重要属性特征。但当你想要给汽车喷漆,换坐垫,或者更换音响时,这些功能是互相可能兼容的,并且他们的存在不会影响车的核心属性:那就是他是一辆什么车。这时你就可以定义一个装饰器:喷了漆的车。不管他装饰的车是宝马还是奥迪,他的喷漆效果都可以实现。



相关文章
|
7月前
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
63 1
聊聊Java设计模式-装饰器模式
|
7月前
|
设计模式 Java
常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)
有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式)
67 2
|
7月前
|
设计模式
设计模式之装饰器模式
设计模式之装饰器模式
|
7月前
|
设计模式
设计模式-装饰器模式
设计模式-装饰器模式
|
2月前
|
设计模式 XML Java
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
34 0
|
7月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
69 1
|
3月前
|
设计模式 Java
Java设计模式-装饰器模式(10)
Java设计模式-装饰器模式(10)
|
6月前
|
设计模式 Java
Java设计模式:深入装饰器模式的三种写法(六)
Java设计模式:深入装饰器模式的三种写法(六)
|
6月前
|
设计模式 架构师 安全
设计模式第五讲-装饰器模式和代理模式详解
远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
274 0
|
7月前
|
设计模式 传感器 数据处理
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
装饰器模式是一种设计模式,它允许在运行时向对象添加额外的职责,而无需修改其代码。这种模式提供了一种动态扩展对象功能的方法,同时保持了对象的单一职责原则。本文介绍了装饰器模式的基本概念、原理、优势、适用场景、实现方法、最佳实践和注意事项。通过装饰器模式,可以将多个行为组合成一个更复杂的行为,而无需使用继承或大量的接口实现。装饰器模式适用于需要对一个对象进行一系列的增强处理的情况,而这些增强处理可以以一种松耦合的方式进行组合。通过使用装饰器模式,可以提高代码的可维护性、可扩展性和灵活性,使系统更加灵活和易于维护
128 1
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀