装饰模式
装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,主要用于在不修改原始类代码的情况下,动态地给对象添加新的职责(功能)。这种模式通过创建一个包装对象(装饰器)来包裹原有的对象,并在这个包装对象中添加新的行为或责任。装饰模式提供了一种灵活的方式来扩展对象的功能,相比通过继承来扩展更为灵活和可控制。
TIP
装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说。装饰模式比生成子类更加灵活
类图
角色
- Component(组件接口):定义一个对象接口,可以给这些对象动态添加职责。
- ConcreteComponent(具体组件):实现了Component接口的类,即需要被装饰的基本对象。
- Decorator(装饰器接口):继承自Component,维护一个指向Component的引用,并定义一个与Component接口一致的接口。
- ConcreteDecorator(具体装饰器):实现Decorator接口,负责给Component添加额外的职责。
优点
- 灵活性高:可以在运行时动态地添加功能,不需要修改原有的类。
- 避免多层继承:通过组合而非继承来扩展功能,减少继承层次的复杂度。
- 重用性好:装饰类可以被多次用来装饰不同的对象,也可以用于装饰其他装饰类,形成装饰链。
应用场景
- 当需要为某些对象动态添加职责,而这些职责可以自由组合的时候。
- 需要为一批同类对象添加不同功能,而又不想通过大量子类来实现的时候。
- 功能需动态开启或关闭,且不想使用复杂的条件语句来控制的时候。
示例
假设有一个简单的文本编辑器,基础功能是显示文本。现在要为文本增加加粗、斜体、下划线等格式化功能,而不修改原始的文本显示类。这里就可以使用装饰模式,定义一个TextDisplay
作为Component,然后为每种格式创建一个Decorator(如BoldDecorator
、ItalicDecorator
),通过叠加这些装饰器,动态地给文本增加多种格式。
首先,我们定义一个基础接口TextComponent
,它是所有文本组件(包括原始文本和装饰器)的基类:
// Component: 基础文本组件接口
interface TextComponent {
String display(); // 显示文本的方法
}
接下来,实现这个接口的基础文本显示类PlainText
,即具体的组件ConcreteComponent
:
// ConcreteComponent: 具体的文本组件 - 简单文本
class PlainText implements TextComponent {
private final String text;
public PlainText(String text) {
this.text = text;
}
@Override
public String display() {
return text;
}
}
定义装饰器接口TextDecorator
,它也实现了TextComponent
接口,并包含一个对TextComponent
的引用,用于维持装饰器和被装饰对象的关系:
// Decorator: 文本装饰器接口
abstract class TextDecorator implements TextComponent {
protected TextComponent textComponent; // 在TextDecorator类中声明textComponent为成员变量
public TextDecorator(TextComponent textComponent) {
this.textComponent = textComponent; // 这里将构造函数参数赋值给成员变量
}
}
然后,创建具体的装饰器类,比如BoldDecorator
(加粗装饰器)和ItalicDecorator
(斜体装饰器):
// ConcreteDecorator: 加粗装饰器
class BoldDecorator extends TextDecorator {
public BoldDecorator(TextComponent textComponent) {
super(textComponent);
}
@Override
public String display() {
return "<b>" + textComponent.display() + "</b>";
}
}
// ConcreteDecorator: 斜体装饰器
class ItalicDecorator extends TextDecorator {
public ItalicDecorator(TextComponent textComponent) {
super(textComponent);
}
@Override
public String display() {
return "<i>" + textComponent.display() + "</i>";
}
}
最后,演示如何使用这些类来动态地给文本添加格式:
public class DecoratorPatternDemo {
public static void main(String[] args) {
// 创建一个原始文本对象
TextComponent plainText = new PlainText("Hello, World!");
// 使用装饰器给文本加粗
TextComponent boldText = new BoldDecorator(plainText);
// 进一步使用装饰器给文本添加斜体
TextComponent italicAndBoldText = new ItalicDecorator(boldText);
// 输出最终的文本效果
System.out.println(italicAndBoldText.display()); // 输出: <i><b>Hello, World!</b></i>
}
}
这段代码展示了如何使用装饰模式来动态地增强对象的功能,而无需修改原始类的代码。通过组合多个装饰器,我们可以灵活地给文本添加多种格式,体现了装饰模式的灵活性和扩展性。
最终显示
<i><b>Hello, World!</b></i>