装饰者模式:动态地为对象添加额外的功能
装饰者模式是什么?为什么需要它?
装饰者模式(又叫包装模式)是一种设计模式,它可以让我们在不改变现有对象的情况下,动态地给对象添加新的功能
。这就像给一只鸟添上翅膀,让它可以飞得更高更远。
在软件开发中,我们经常会遇到需要给对象添加新功能的情况。传统的做法是通过继承来扩展对象的功能,但这样会导致类的爆炸,增加了代码的复杂性
。而装饰者模式提供了一种更灵活的解决方案。
怎么使用装饰者模式?
核心组成:
- 抽象组件(Component):
定义了被装饰对象和装饰对象的共同接口,可以是抽象类或接口。它定义了基本的操作方法,是装饰者和被装饰者的共同父类
。 - 具体组件(Concrete Component):
实现了抽象组件接口,是被装饰的对象。它定义了基本的功能,可以被装饰者直接使用。
- 抽象装饰者(Decorator):
也是抽象组件的子类,持有一个抽象组件的引用。它定义了装饰者的共同接口,并在内部调用抽象组件的方法。
- 具体装饰者(Concrete Decorator):
实现了抽象装饰者接口,是具体的装饰者对象。它持有一个抽象组件的引用,并可以在调用抽象组件的方法之前或之后添加额外的功能。
核心思想:
通过组合来实现功能的扩展
。我们首先定义一个抽象的组件接口,它规定了被包装对象和包装对象的共同行为。然后,我们有一个具体的组件类,它实现了这个接口并提供了基本的功能
。
接下来,我们有一个抽象的装饰器类,它也实现了组件接口,并持有一个组件对象的引用。装饰器类可以通过组合多个装饰器对象来实现对组件的包装。装饰器类可以在调用组件的方法之前或之后添加额外的功能。
使用案例
下面通过一个点餐案例来说一下装饰者模式,通过装饰者模式,可以动态地给点餐对象添加额外的功能
,比如加饮料、加甜点等。
- 抽象组件:点餐(Order)
- 具体组件(被装饰者):普通点餐(RegularOrder)
- 抽象装饰者:点餐装饰者(OrderDecorator)
- 具体装饰者:加饮料(DrinkDecorator)、加甜点(DessertDecorator)
// 抽象组件:点餐
interface Order {
String getDescription();
double getPrice();
}
// 具体组件:普通点餐
class RegularOrder implements Order {
@Override
public String getDescription() {
return "普通点餐";
}
@Override
public double getPrice() {
return 10.0;
}
}
// 抽象装饰者:点餐装饰者
abstract class OrderDecorator implements Order {
protected Order order;
public OrderDecorator(Order order) {
this.order = order;
}
@Override
public String getDescription() {
return order.getDescription();
}
@Override
public double getPrice() {
return order.getPrice();
}
}
// 具体装饰者:加饮料
class DrinkDecorator extends OrderDecorator {
public DrinkDecorator(Order order) {
super(order);
}
@Override
public String getDescription() {
return order.getDescription() + " + 饮料";
}
@Override
public double getPrice() {
return order.getPrice() + 5.0;
}
}
// 具体装饰者:加甜点
class DessertDecorator extends OrderDecorator {
public DessertDecorator(Order order) {
super(order);
}
@Override
public String getDescription() {
return order.getDescription() + " + 甜点";
}
@Override
public double getPrice() {
return order.getPrice() + 8.0;
}
}
public class Main {
public static void main(String[] args) {
// 创建一个普通点餐对象
Order order = new RegularOrder();
System.out.println("点餐:" + order.getDescription());
System.out.println("价格:" + order.getPrice());
// 加饮料
order = new DrinkDecorator(order);
System.out.println("点餐:" + order.getDescription());
System.out.println("价格:" + order.getPrice());
// 加甜点
order = new DessertDecorator(order);
System.out.println("点餐:" + order.getDescription());
System.out.println("价格:" + order.getPrice());
}
}
源码分析
以Java IO库中的InputStream
为例:
- 抽象组件:InputStream,装饰者模式中的超类,它只有一个抽象方法read(),子类都需要对该方法进行处理
- 具体组件(被装饰者):FileInputStream , ByteArrayInputStream ,StringBufferInputStream,被装饰者,拥有通用实现read()基本方法
- 抽象装饰者:FilterInputStream定义具体装饰者的行为规范,可以做统一基础处理。
- 具体装饰者:BufferedInputStream , DataInputStream , Base64InputStream具体的装饰类,拥有对流的读操作做完成具体拓展能力。
总结
装饰者模式的优点在于它提供了一种灵活的方式来给对象添加新的功能,同时保持了对象接口的一致性。它避免了使用继承来扩展对象功能的问题,避免了类的爆炸。同时,它也可以保持代码的可读性和可维护性。
总的来说,装饰者模式是一种非常有用的设计模式,它可以让我们在不改变现有对象
的情况下,动态地给对象添加新的功能
。通过组合多个装饰器对象,我们可以实现不同的功能组合
。这种灵活性使得装饰者模式在软件开发中有广泛的应用。就像给一只鸟添上翅膀,包装模式可以让我们的对象飞得更高更远。
欢迎评论区或私信交流,共同进步。