【设计模式系列7】装饰器模式

简介: 突然想写这个设计模式,是因为刚看了FactoryBean,因为它通过装饰模式,来进一步修饰Bean对象,所以想看看这个模式是怎么使用的。我理解这个设计模式,就是基于原来的对象进行装饰。

85}S3BMVM)8HO8W_)(5LL9K.png

主要讲解装饰器Decoration模式。


前言


突然想写这个设计模式,是因为刚看了FactoryBean,因为它通过装饰模式,来进一步修饰Bean对象,所以想看看这个模式是怎么使用的。我理解这个设计模式,就是基于原来的对象进行装饰。


装饰器模式


基本概念

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

使用场景:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

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

image.gif

装饰器示例

先定义一个Food的抽象类:

public abstract class Food {
    protected String desc;
    public abstract String getDesc();
}


然后实例化2个实物对象,比如鸡肉和鸭肉:

public class Chicken extends Food {
    public Chicken() {
        this.desc = "鸡肉";
    }
    @Override
    public String cook() {
        return this.desc;
    }
}
public class Duck extends Food {
    public Duck() {
        this.desc = "鸭肉";
    }
    @Override
    public String cook() {
        return this.desc;
    }
}


再定义一个装饰的抽象类,这个是继承了Food:

public abstract class FoodDecoration extends Food {
    @Override
    public abstract String cook();
}


再定义两个不同的装饰类,一个是烤,一个是蒸:

public class RoastFood extends FoodDecoration {
    private Food food;
    public RoastFood(Food f){
        this.food = f;
    }
    @Override
    public String cook() {
        return getDecoration() + food.cook();
    }
    private String getDecoration(){
        return "烤";
    }
}
public class SteamedFood extends FoodDecoration{
    private Food food;
    public SteamedFood(Food food) {
        this.food = food;
    }
    private String getDecoration() {
        return "蒸";
    }
    @Override
    public String cook() {
        return this.getDecoration() + food.cook();
    }
}


最后我们可以对实物进行装饰:

public static void main(String args[]) {
    // 测试单纯的食物
    Chicken chicken = new Chicken();
    System.out.println(chicken.cook());
    // 测试单重修饰的食物
    RoastFood roastFood = new RoastFood(chicken);
    System.out.println(roastFood.cook());
    // 测试多重修饰的食物
    SteamedFood steamedFood = new SteamedFood(roastFood);
    System.out.println(steamedFood.cook());
}
// 输出:
// 鸡肉
// 烤鸡肉
// 蒸烤鸡肉


评价一下,装饰类主要是需要定义一个通用的抽象方法或者接口,供实体对象和装饰对象继承,并通过装饰类修饰该对象。因为通过修饰类对外暴露的cook()方法和原对象一致(肯定是一致的,因为他们重写同一个方法),所以这个装饰类对象就可以当做源对象使用,不同的是对源对象做了一层装饰。


所以我们在“多重修饰”中可以看到,我们把装饰后的对象roastFood,直接当做实物对象使用,完全没有任何问题,虽然它本质上和实物对象不同,但是使用效果确是一致的(这个和我们平时开发一样,将一个对象作为自己的成员类变量,然后对外暴露的方法,其实就是把该成员类变量的方法包一层,道理是一样的)。

所以回过头来,我们再看FactoryBean,其实它应该也有一个成员类变量,我们通过Bean初始化FactoryBean时,就可以通过FactoryBean对这个Bean进行装饰。


优缺点


优点

  1. 装饰者模式可以提供比继承更多的灵活性
  2. 可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
  3. 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
  4. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

缺点

  1. 会产生很多的小对象,增加了系统的复杂性
  2. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
相关文章
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
155 1
聊聊Java设计模式-装饰器模式
|
设计模式 Java
常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)
有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式)
180 2
|
设计模式
设计模式之装饰器模式
设计模式之装饰器模式
|
设计模式
设计模式-装饰器模式
设计模式-装饰器模式
103 0
|
设计模式 XML Java
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)
138 0
|
10月前
|
设计模式 中间件 Java
设计模式3:代理、适配器、装饰器模式
代理模式是一种结构型设计模式,通过中间件解耦服务提供者和使用者,使使用者间接访问服务提供者,便于封装和控制。
178 3
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
184 1
|
12月前
|
设计模式 前端开发 JavaScript
前端必须掌握的设计模式——装饰器模式
装饰器模式是一种结构型设计模式,通过创建新类来包装原始对象,实现在不修改原有结构的前提下扩展新行为。其核心在于“组合”思想,使新功能可“即插即拔”。该模式具有解耦性、灵活性和动态性等特点,广泛应用于类的面向对象编程语言中,如JavaScript的注解和TypeScript的写法。示例中,通过装饰器模式为游戏角色动态添加装备,展示了其强大的扩展性和灵活性。
253 16
|
设计模式 Java
Java设计模式-装饰器模式(10)
Java设计模式-装饰器模式(10)
120 2
|
设计模式 传感器 数据处理
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
装饰器模式是一种设计模式,它允许在运行时向对象添加额外的职责,而无需修改其代码。这种模式提供了一种动态扩展对象功能的方法,同时保持了对象的单一职责原则。本文介绍了装饰器模式的基本概念、原理、优势、适用场景、实现方法、最佳实践和注意事项。通过装饰器模式,可以将多个行为组合成一个更复杂的行为,而无需使用继承或大量的接口实现。装饰器模式适用于需要对一个对象进行一系列的增强处理的情况,而这些增强处理可以以一种松耦合的方式进行组合。通过使用装饰器模式,可以提高代码的可维护性、可扩展性和灵活性,使系统更加灵活和易于维护
355 1
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀

热门文章

最新文章