装饰器模式(Decorator Pattern),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更灵活。 —-《大话设计模式》
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
共同点:都拥有一个目标对象。装饰器通过包装一个装饰对象来扩展其功能,而又不改变其接口,这实际上是基于对象的适配器模式的一种变种。
不同点:适配器模式需要实现另外一个接口,而装饰器模式必须实现该对象的接口。适配器模式主要是为了接口的转换,而装饰者模式关注的是通过组合来动态的为被装饰者注入新的功能或行为(即所谓的责任)。
适配器模式详解传送门:JAVA设计模式-适配器模式_Mr Tang的博客-CSDN博客
假设我去买咖啡,首先服务员给我冲了一杯原味咖啡,我希望服务员给我加些牛奶和白糖混合入原味咖啡中。使用装饰器模式就可以解决这个问题。
定义了获取花费和配料的接口。
/**
* 咖啡接口
*/
public interface Coffee {
/**
* 获取价格
* @return
*/
public float getPrice();
/**
* 获取咖啡
* @return
*/
public String getCoffee();
}
实现Coffe接口,花费1元,配料中,只有咖啡
/**
* 原味咖啡类
*/
public class OriginalCoffee implements Coffee {
@Override
public float getPrice() {
return 1;
}
@Override
public String getCoffee() {
return "原味咖啡";
}
}
咖啡对象的装饰器类,同样实现Coffee接口,定义一个Coffe对象的引用,在构造器中进行初始化。并且将getPrice()和getCoffee()方法转发给被装饰对象。
/**
* 咖啡的"装饰器",可以给咖啡添加各种"配料"
* 该类是一个抽象类需要具体子类来实现
*/
public class DecoratorAbstractCoffee implements Coffee {
/**
* 具体咖啡的接口
*/
protected final Coffee coffee;
/**
* 构造方法,初始化咖啡对象的引用
* @param coffee
*/
public DecoratorAbstractCoffee(Coffee coffee) {
this.coffee = coffee;
}
/**
* 获取价格,装饰器父类中直接转发"请求"至引用对象
* @return
*/
@Override
public float getPrice() {
return coffee.getPrice();
}
/**
* 获取咖啡,装饰器父类中直接转发"请求"至引用对象
* @return
*/
@Override
public String getCoffee() {
return coffee.getCoffee();
}
}
具体的装饰器类,负责往咖啡中“添加”牛奶,注意看getPrice()方法和getCoffee()方法,可以在转发请求之前或者之后,增加功能。如果是代理模式,这里的结构就有所不同,通常代理模式根据运行时的条件来判断是否转发请求。
/**
* 混合牛奶到蜂蜜中
*/
public class CreamCoffee extends DecoratorAbstractCoffee {
private float price = (float) 0.5;
/**
* 调用父类的构造方法
* @param coffee
*/
public CreamCoffee(Coffee coffee) {
super(coffee);
}
/**
* 增加配料需要加钱
* @return
*/
@Override
public float getPrice() {
return coffee.getPrice()+price;
}
/**
* 对咖啡进行加工
* @return
*/
@Override
public String getCoffee() {
return coffee.getCoffee()+";添加牛奶";
}
}
另一个具体装饰器类,用来给咖啡加蜂蜜,一样的逻辑。
class HoneyCoffee extends DecoratorAbstractCoffee {
private float price = (float) 1.4;
public HoneyCoffee(Coffee coffee) {
super(coffee);
}
@Override
public float getPrice() {
return coffee.getPrice()+price;
}
@Override
public String getCoffee() {
return coffee.getCoffee()+";添加蜂蜜";
}
}
public class DecoratorMain {
public static void main(String[] args) {
//是不是很像 javaIO中的 stream流
Coffee coffee = new CreamCoffee(new HoneyCoffee(new OriginalCoffee()));
System.out.println(coffee.getCoffee());
System.out.println(coffee.getPrice());
}
}
装饰者模式在Spring Boot中有着广泛的应用,主要用于动态地扩展和改变对象的行为和状态。以下是装饰者模式在Spring Boot中的一些常见应用:
这些应用只是装饰者模式在Spring Boot中的一部分。事实上,只要你需要动态地扩展和改变对象的行为和状态,装饰者模式就可能是一个好的解决方案。
装饰器模式是代替增加子类的一种解决方案,体现了聚合/合成复用原则的思想,尽量使用组合的方式来扩展功能,这样就把基本功能和扩展功能解耦了,使得代码可复用,可维护,灵活。关键点在于装饰器模式可以动态地为对象增加扩展功能。