当前位置: 首页 > news >正文

装饰器模式介绍和典型实现

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象添加新的功能。装饰器模式的主要优点是可以在运行时动态地添加功能,而不需要修改原对象的代码。这使得代码更加灵活和可扩展。

装饰器模式的说明

角色
  1. Component(组件)

    • 定义了对象的接口,可以给这些对象动态地添加职责。
    • 可以是抽象类或接口。
  2. ConcreteComponent(具体组件)

    • 实现了 Component 接口,定义了具体的业务逻辑。
  3. Decorator(装饰器)

    • 也实现了 Component 接口,但其主要职责是为组件动态地添加功能。
    • 通常包含一个对 Component 的引用,以便调用被装饰对象的方法。
  4. ConcreteDecorator(具体装饰器)

    • 实现了 Decorator,添加了具体的功能。
  5. Client(客户端)

    • 通过 Component 接口操作对象,无需关心对象的具体类型。

经典框架中的实现案例

1. Java I/O 框架

Java I/O 框架中的 InputStreamOutputStream 类及其子类(如 BufferedInputStreamDataInputStream 等)是装饰器模式的经典应用。

  • Component(组件)InputStreamOutputStream
  • ConcreteComponent(具体组件)FileInputStreamFileOutputStream
  • Decorator(装饰器)BufferedInputStreamDataInputStreamBufferedOutputStreamDataOutputStream
  • ConcreteDecorator(具体装饰器)BufferedInputStreamDataInputStreamInputStream 添加了缓冲和数据读取功能;BufferedOutputStreamDataOutputStreamOutputStream 添加了缓冲和数据写入功能。
import java.io.*;

public class JavaIOCompositeExample {

    public static void main(String[] args) {
        try {
            // 创建 FileInputStream
            InputStream fileInputStream = new FileInputStream("input.txt");

            // 创建 BufferedInputStream
            InputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

            // 创建 DataInputStream
            InputStream dataInputStream = new DataInputStream(bufferedInputStream);

            // 读取数据
            int data;
            while ((data = dataInputStream.read()) != -1) {
                System.out.print((char) data);
            }

            // 关闭流
            dataInputStream.close();

            // 创建 FileOutputStream
            OutputStream fileOutputStream = new FileOutputStream("output.txt");

            // 创建 BufferedOutputStream
            OutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

            // 创建 DataOutputStream
            OutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);

            // 写入数据
            dataOutputStream.writeBytes("Hello, World!");

            // 关闭流
            dataOutputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中:

  • FileInputStreamFileOutputStream 是具体组件,提供基本的文件读写功能。
  • BufferedInputStreamBufferedOutputStream 是装饰器,为文件读写添加了缓冲功能。
  • DataInputStreamDataOutputStream 是具体装饰器,为文件读写添加了数据读写功能。
  • 客户端代码通过装饰器链来读写文件,而不需要关心具体的功能实现。
2. Spring AOP

Spring AOP(Aspect-Oriented Programming)框架中的切面(Aspect)和通知(Advice)可以看作是装饰器模式的应用。通过 AOP,可以在运行时动态地为方法添加额外的功能,如日志记录、事务管理等。

  • Component(组件):业务逻辑方法。
  • ConcreteComponent(具体组件):具体的业务逻辑实现。
  • Decorator(装饰器):切面(Aspect)。
  • ConcreteDecorator(具体装饰器):通知(Advice),如 @Before@After@Around 等。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@Aspect
public class LoggingAspect {
    @Before("execution(* com.example.service.MyService.doSomething(..))")
    public void logBefore() {
        System.out.println("Logging before method execution");
    }
}

public class MyService {
    public void doSomething() {
        System.out.println("Doing something in MyService");
    }
}

public class SpringAOPCompositeExample {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MyService.class, LoggingAspect.class);
        context.refresh();

        MyService myService = context.getBean(MyService.class);
        myService.doSomething();

        context.close();
    }
}

在这个例子中:

  • MyService 是具体组件,定义了具体的业务逻辑。
  • LoggingAspect 是装饰器,通过 @Before 注解为 MyServicedoSomething 方法添加了日志记录功能。
  • 客户端代码通过 Spring 容器获取 MyService 的实例,并调用其方法,而不需要关心日志记录的具体实现。

3. MyBatis 框架

MyBatis 框架中的 Interceptor 机制也可以看作是装饰器模式的应用。通过 Interceptor,可以在 SQL 执行前后添加额外的逻辑,如缓存、日志记录等。

  • Component(组件)Executor 接口。
  • ConcreteComponent(具体组件)BaseExecutor 类。
  • Decorator(装饰器)Interceptor 接口。
  • ConcreteDecorator(具体装饰器):具体的 Interceptor 实现。
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.plugin.*;

import java.util.Properties;

@Intercepts({@Signature(type = Executor.class, method = "update", args = {String.class, Object.class})})
public class MyInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("Intercepting before update method execution");
        Object result = invocation.proceed();
        System.out.println("Intercepting after update method execution");
        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 设置属性
    }
}

public class MyBatisCompositeExample {

    public static void main(String[] args) {
        // 创建 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = MyBatisCompositeExample.class.getClassLoader().getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 注册 Interceptor
        sqlSessionFactory.getConfiguration().addInterceptor(new MyInterceptor());

        // 获取 SqlSession
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 获取 Mapper
            UserMapper userMapper = session.getMapper(UserMapper.class);

            // 执行更新操作
            userMapper.updateUser(new User(1, "John Doe"));
        }
    }
}

// User 类
public class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters and Setters
}

// UserMapper 接口
public interface UserMapper {
    void updateUser(User user);
}

// mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

// UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <update id="updateUser" parameterType="com.example.model.User">
        UPDATE users
        SET name = #{name}
        WHERE id = #{id}
    </update>
</mapper>

在这个例子中:

  • Executor 是组件,负责执行 SQL 语句。
  • BaseExecutor 是具体组件,提供了基本的 SQL 执行功能。
  • MyInterceptor 是具体装饰器,通过 @Intercepts 注解为 Executorupdate 方法添加了日志记录功能。
  • 客户端代码通过 SqlSessionFactory 获取 SqlSession,再通过 SqlSession 获取 UserMapper,并调用其方法,而不需要关心日志记录的具体实现。

运行结果

Intercepting before update method execution
Doing something in MyService
Intercepting after update method execution

解释

  1. Component(组件)

    • Executor 接口定义了执行 SQL 语句的方法。
    • BaseExecutor 类实现了 Executor 接口,提供了基本的 SQL 执行功能。
  2. Decorator(装饰器)

    • Interceptor 接口定义了拦截器的方法。
    • MyInterceptor 类实现了 Interceptor 接口,添加了日志记录功能。
  3. ConcreteDecorator(具体装饰器)

    • MyInterceptor 通过 intercept 方法在 SQL 执行前后添加日志记录功能。
  4. Client(客户端)

    • 客户端代码通过 SqlSessionFactory 获取 SqlSession,再通过 SqlSession 获取 UserMapper,并调用其方法,而不需要关心日志记录的具体实现。

总结

  1. Java I/O 框架

    • 通过 InputStreamOutputStream 的装饰器(如 BufferedInputStreamDataInputStream)动态地添加功能,使得 I/O 操作更加灵活和高效。
  2. Spring AOP

    • 通过切面(Aspect)和通知(Advice)为方法动态地添加额外的功能,如日志记录、事务管理等,使得业务逻辑更加清晰和模块化。
  3. MyBatis 框架

    • 通过 Interceptor 机制为 SQL 执行动态地添加额外的功能,如日志记录、缓存等,使得 SQL 操作更加灵活和可扩展。

通过这些经典实现,可以看到装饰器模式在实际应用中的强大之处,它不仅简化了客户端代码,还提高了系统的可维护性和扩展性。

相关文章:

  • k8s常用命令
  • js的闭包
  • linux 运行脚本命令区别
  • Pinecone数据库介绍、Milvus数据库介绍
  • 基于FastAPI与Kimi AI的智能聊天应用开发实践
  • 6. 使用VUE实现前端页面的分级嵌套
  • Spring Boot集成阿里云OSS:对象存储实战指南
  • 【学习】数字经济下数据价值化的内在逻辑与关键挑战
  • Vue的实例
  • SpringBoot整合Log4j2进行日志记录异步写入日志文件
  • 《深度剖析Android 12 SystemUI锁屏通知布局亮屏流程:从源码到实现》
  • 0323-B树、B+树
  • Mybatis-plus配置动态多数据源
  • Linux系统之yum本地仓库创建
  • EMC知识学习一
  • 【android】补充
  • Jenkins 配置python项目和allure
  • 【HTML 基础教程】HTML 元素
  • 逼用户升级Win11,微软开始给Win10限速
  • 使用 langchain_deepseek 实现自然语言转数据库查询SQL
  • 妹子ui wordpress/长沙seo技术培训
  • 购物网站的功能板块/seo免费培训视频
  • 网站建设要什么知识/淘宝seo排名优化软件
  • 一个小程序开发费用/seo搜索引擎优化实战
  • 真实家庭装修图片/网站搜索引擎优化主要方法
  • 展现真实网站/facebook海外推广