结构型模式(一):适配器模式、装饰器模式
- 1.适配器模式(Adapter)
- 2.装饰器模式(Decorator)
- 2.1 主要特点
- 2.2 组成部分
- 2.3 示例代码
- 2.3.1 Component 组件
- 2.3.2 ConcreteComponent 具体组件
- 2.3.3 Decorator 装饰器
- 2.3.4 ConcreteDecorator 具体装饰器
- 2.3.5 客户端代码
- 2.4 总结
1.适配器模式(Adapter)
适配器模式(Adapter Pattern
)是一种结构型设计模式,其主要目的是通过适配器将一个接口转换为客户端所期望的另一个接口。这个模式允许你为现有类增加新功能,或者让它们之间兼容,而无需修改其源代码。适配器模式可以分为两类:
- 类适配器模式:通过继承来适配一个类的接口。
- 对象适配器模式:通过组合来适配一个类的接口。
适配器模式主要包含以下角色:
- 目标接口(
Target
):这是客户端所期望的接口,可以是一个类或一个接口。 - 适配者(
Adaptee
):这是需要适配的接口,即拥有不兼容接口的对象。 - 适配器(
Adapter
):这是关键部分,它 持有适配者对象的实例,并且可以 调用适配者的方法,同时 实现目标接口,从而使得适配者接口和目标接口兼容。
假设有一个类 AmericanPlug
,其接口与我们的需求不兼容。我们希望使用这个类,但需要将其适配到我们所需的接口 ChinesePlug
。
// 目标接口
interface ChinesePlug {
void connect();
}
// 适配者
class AmericanPlug {
public void plugIn() {
System.out.println("American Plug is connected.");
}
}
// 适配器
class Adapter extends AmericanPlug implements ChinesePlug {
@Override
public void connect() {
super.plugIn();
}
}
public class AdapterPatternExample {
public static void main(String[] args) {
ChinesePlug plug = new Adapter();
plug.connect(); // 输出 "American Plug is connected."
}
}
在这个例子中,Adapter
类继承了 AmericanPlug
类并实现了 ChinesePlug
接口。通过这个适配器,客户端可以使用 ChinesePlug
接口,而实际上调用的是 AmericanPlug
类的方法。
适配器模式可以使得你复用现有的类,而不必修改它们的接口,同时增加了系统的灵活性和可扩展性。
2.装饰器模式(Decorator)
装饰器模式(Decorator Pattern
)是一种结构型设计模式,允许在运行时动态地为对象添加行为和职责,而不需要修改对象的结构。通过这种方式,可以 在不使用子类的情况下扩展对象的功能,提供了一种灵活的替代继承的方案。
2.1 主要特点
- 动态扩展:可以在运行时动态地为对象添加功能,而不需要修改原有的类。
- 透明性:装饰器类和被装饰的类具有相同的接口,客户端代码可以在不改变代码的情况下使用装饰后的对象。
- 组合优于继承:避免了大量子类的产生,使代码更加灵活和可维护。
2.2 组成部分
Component
(组件):- 定义一个接口或抽象类,表示 被装饰的对象。
- 具体组件实现这个接口或抽象类。
ConcreteComponent
(具体组件):- 实现 Component 接口,提供基本的行为或功能。
Decorator
(装饰器):- 持有一个 Component 对象的引用。
- 实现 Component 接口,可以在调用具体组件的方法前后添加新的行为。
ConcreteDecorator
(具体装饰器):- 继承自 Decorator,实现具体的装饰行为。
2.3 示例代码
以下是一个简单的 Java 示例,展示了如何使用装饰器模式为文本添加不同的格式。
2.3.1 Component 组件
// Component 组件
interface TextComponent {
String getText();
}
TextComponent
:定义了一个接口,声明了一个getText
方法。这个接口表示 被装饰的对象 的基本行为。
2.3.2 ConcreteComponent 具体组件
// ConcreteComponent 具体组件
class SimpleText implements TextComponent {
private String text;
public SimpleText(String text) {
this.text = text;
}
@Override
public String getText() {
return text;
}
}
SimpleText
:实现了TextComponent
接口,提供了一个具体的文本实现。- 属性:
text
,存储具体的文本内容。 - 构造方法:
SimpleText(String text)
,初始化文本内容。 - 方法:
getText()
,返回存储的文本内容。
- 属性:
2.3.3 Decorator 装饰器
// Decorator 装饰器
abstract class TextDecorator implements TextComponent {
protected TextComponent component;
public TextDecorator(TextComponent component) {
this.component = component;
}
@Override
public String getText() {
return component.getText();
}
}
TextDecorator
:抽象类,持有一个TextComponent
对象的引用,实现了TextComponent
接口。- 属性:
component
,存储被装饰的组件。 - 构造方法:
TextDecorator(TextComponent component)
,初始化 被装饰的组件。 - 方法:
getText()
,调用被装饰组件的getText
方法,返回其文本内容。这个方法在具体装饰器中可以被重写,以添加额外的行为。
- 属性:
2.3.4 ConcreteDecorator 具体装饰器
// ConcreteDecorator 具体装饰器
class BoldTextDecorator extends TextDecorator {
public BoldTextDecorator(TextComponent component) {
super(component);
}
@Override
public String getText() {
return "<b>" + super.getText() + "</b>";
}
}
class ItalicTextDecorator extends TextDecorator {
public ItalicTextDecorator(TextComponent component) {
super(component);
}
@Override
public String getText() {
return "<i>" + super.getText() + "</i>";
}
}
BoldTextDecorator
:具体的装饰器,继承自TextDecorator
,为文本添加粗体格式。- 方法:
getText()
,在被装饰组件的文本内容前后添加<b>
和</b>
标签。
- 方法:
ItalicTextDecorator
:具体的装饰器,继承自TextDecorator
,为文本添加斜体格式。- 方法:
getText()
,在被装饰组件的文本内容前后添加<i>
和</i>
标签。
- 方法:
2.3.5 客户端代码
// 客户端代码
public class DecoratorPatternExample {
public static void main(String[] args) {
// 创建一个简单的文本组件
TextComponent simpleText = new SimpleText("Hello, World!");
// 为简单文本添加粗体装饰
TextComponent boldText = new BoldTextDecorator(simpleText);
// 为粗体文本添加斜体装饰
TextComponent italicBoldText = new ItalicTextDecorator(boldText);
System.out.println(simpleText.getText()); // 输出原始文本: Hello, World!
System.out.println(boldText.getText()); // 输出粗体文本: <b>Hello, World!</b>
System.out.println(italicBoldText.getText()); // 输出斜体和粗体文本: <i><b>Hello, World!</b></i>
}
}
2.4 总结
通过装饰器模式,可以在不修改原有类的情况下,动态地为对象添加新的功能。这种方式使得代码更加灵活和可扩展,避免了大量子类的产生。
- 优点
- 灵活性:可以在运行时动态地添加或删除功能。
- 可扩展性:通过组合不同的装饰器,可以轻松地创建复杂的对象。
- 代码复用:避免了大量子类的产生,减少了代码的复杂性。
- 缺点
- 复杂性:过多的装饰器可能会使代码变得复杂,难以维护。
- 性能:每次调用方法时都需要额外的处理,可能会有性能开销。
装饰器模式在许多框架和库中都有应用,例如 Java I/O 流中的 BufferedInputStream
和 DataInputStream
,以及 Spring 框架中的 AOP(面向切面编程)。