一、概述
装饰器模式(Decorator Pattern),从分类上讲,属于结构型模式。它是作为现有的类的一个包装。
该模式允许动态地给一个对象添加一些额外的职责。同时又不改变其原有结构。
主要应用场景:
一般,我们使用继承方式扩展一个类。然而随着扩展功能不断增多,子类会逐渐膨胀。
而装饰器模式就是为了解决这个问题的。它抽离出核心功能和扩展功能。从而进行动态扩展而无需创建新的继承子类。
二、UML图
-
抽象组件角色(Component): 定义可以动态添加任务的对象的接口
-
具体组件角色(ConcreteComponent):定义一个要被装饰器装饰的对象,即Component 的具体实现
-
抽象装饰器(Decorator): 实现了Component接口,维护对组件对象和其子类组件的引用
-
具体装饰器角色(ConcreteDecorator):向组件添加新的职责
三、源码
//基础接口
public interface Component {
public void operation();
}
//具体实现类
public class ConcretComponent implements Component {
public void operation() {
System.out.println("核心类操作");
}
}
//装饰类
public class Decorator implements Component {
public Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
this.component.operation();
}
}
//具体装饰类
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
System.out.println("装饰类操作");
this.component.operation();
}
}
四、装饰器模式在实际应用中的例子
在Java的I/O系统设计上就用到了该模式。因为Java I/O类库需要多种不同功能的组合。
InputStream作为抽象构件,它有几种具体基础构件
-
ByteArrayInputStream,从字节数组产生输入;
-
FileInputStream,从文件产生输入;
-
StringBufferInputStream,从String对象产生输入;
-
PipedInputStream,从管道产生输入;
-
SequenceInputStream,可将其他流收集合并到一个流内;
FilterInputStream作为装饰器,其下面有多个具体装饰器比如BufferedInputStream、DataInputStream等。
BufferedInputStream为具体装饰类,扩展I/O输入流的功能,即每次读取时都进行缓冲。
五、简单例子
// 定义咖啡接口
interface Coffee {
fun getDescription(): String
fun cost(): Double
}
// 基础咖啡类
class SimpleCoffee : Coffee {
override fun getDescription(): String {
return "Coffee"
}
override fun cost(): Double {
return 2.0 // 基础咖啡价格
}
}
// 装饰器抽象类
abstract class CoffeeDecorator(private val coffee: Coffee) : Coffee {
override fun getDescription(): String {
return coffee.getDescription()
}
override fun cost(): Double {
return coffee.cost()
}
}
// 牛奶装饰器
class MilkDecorator(coffee: Coffee) : CoffeeDecorator(coffee) {
override fun getDescription(): String {
return super.getDescription() + ", Milk"
}
override fun cost(): Double {
return super.cost() + 0.5 // 加牛奶的价格
}
}
// 香草装饰器
class VanillaDecorator(coffee: Coffee) : CoffeeDecorator(coffee) {
override fun getDescription(): String {
return super.getDescription() + ", Vanilla"
}
override fun cost(): Double {
return super.cost() + 0.7 // 加香草的价格
}
}
// 示例用法
fun main() {
var myCoffee: Coffee = SimpleCoffee()
println("${myCoffee.getDescription()} costs ${myCoffee.cost()}")
// 加牛奶的拿铁
myCoffee = MilkDecorator(myCoffee)
println("${myCoffee.getDescription()} costs ${myCoffee.cost()}")
// 加香草的拿铁
myCoffee = VanillaDecorator(myCoffee)
println("${myCoffee.getDescription()} costs ${myCoffee.cost()}")
// 创建卡布奇诺
var cappuccino: Coffee = SimpleCoffee()
cappuccino = MilkDecorator(cappuccino) // 加牛奶
println("${cappuccino.getDescription()} costs ${cappuccino.cost()}")
}