【设计模式】结构型模式(一):适配器模式、装饰器模式

结构型模式(一):适配器模式、装饰器模式

  • 1.适配器模式(Adapter)
  • 2.装饰器模式(Decorator)
    • [2.1 主要特点](#2.1 主要特点)
    • [2.2 组成部分](#2.2 组成部分)
    • [2.3 示例代码](#2.3 示例代码)
      • [2.3.1 Component 组件](#2.3.1 Component 组件)
      • [2.3.2 ConcreteComponent 具体组件](#2.3.2 ConcreteComponent 具体组件)
      • [2.3.3 Decorator 装饰器](#2.3.3 Decorator 装饰器)
      • [2.3.4 ConcreteDecorator 具体装饰器](#2.3.4 ConcreteDecorator 具体装饰器)
      • [2.3.5 客户端代码](#2.3.5 客户端代码)
    • [2.4 总结](#2.4 总结)

1.适配器模式(Adapter)

适配器模式Adapter Pattern)是一种结构型设计模式,其主要目的是通过适配器将一个接口转换为客户端所期望的另一个接口。这个模式允许你为现有类增加新功能,或者让它们之间兼容,而无需修改其源代码。适配器模式可以分为两类:

  • 类适配器模式:通过继承来适配一个类的接口。
  • 对象适配器模式:通过组合来适配一个类的接口。

适配器模式主要包含以下角色:

  • 目标接口Target):这是客户端所期望的接口,可以是一个类或一个接口。
  • 适配者Adaptee):这是需要适配的接口,即拥有不兼容接口的对象。
  • 适配器Adapter):这是关键部分,它 持有适配者对象的实例 ,并且可以 调用适配者的方法 ,同时 实现目标接口,从而使得适配者接口和目标接口兼容。

假设有一个类 AmericanPlug,其接口与我们的需求不兼容。我们希望使用这个类,但需要将其适配到我们所需的接口 ChinesePlug

java 复制代码
// 目标接口
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 组件

java 复制代码
// Component 组件
interface TextComponent {
    String getText();
}
  • TextComponent:定义了一个接口,声明了一个 getText 方法。这个接口表示 被装饰的对象 的基本行为。

2.3.2 ConcreteComponent 具体组件

java 复制代码
// 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 装饰器

java 复制代码
// 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 具体装饰器

java 复制代码
// 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 客户端代码

java 复制代码
// 客户端代码
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 流中的 BufferedInputStreamDataInputStream,以及 Spring 框架中的 AOP(面向切面编程)。

相关推荐
快意咖啡~2 分钟前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio
IT枫斗者30 分钟前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网
爱编程的小生31 分钟前
Easyexcel(4-模板文件)
java·excel
求积分不加C33 分钟前
Kafka怎么发送JAVA对象并在消费者端解析出JAVA对象--示例
java·分布式·kafka·linq
2401_8576363937 分钟前
实验室管理平台:Spring Boot技术构建
java·spring boot·后端
问窗41 分钟前
微服务中Spring boot的包扫描范围
java·spring boot·微服务
是程序喵呀1 小时前
SpringMVC详解
java·spring·spring-mvc
疯一样的码农1 小时前
Apache Maven 标准文件目录布局
java·maven·apache
Felix666yy1 小时前
设计模式之建造者模式
java
界面开发小八哥1 小时前
「Java EE开发指南」如何使用Visual JSF编辑器设计JSP?(一)
java·ide·java-ee·编辑器·myeclipse