JAVA设计模式之适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成另外一个接口,从而使原本不兼容的接口可以一起工作。适配器模式通常用于系统间接口的兼容性问题,可以将已有的接口适配成另一个接口,以满足客户端的需求。

适配器模式由三个角色组成:

  • 目标接口(Target):客户端需要的接口。
  • 源接口(Adaptee):需要被适配的接口。
  • 适配器(Adapter):将源接口适配成目标接口的中间件。

下面以一个示例来说明适配器模式的应用。

假设我们有一个接口 Target,它定义了一个 request 方法:

public interface Target {
    void request();
}

然后我们有一个现有的类 Adaptee,它定义了一个不兼容的 specificRequest 方法:

public class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee specificRequest");
    }
}

现在我们需要将 Adaptee 类的接口适配成 Target 接口,以便客户端可以使用它。

首先,我们定义一个适配器类 Adapter,实现 Target 接口,并包含一个 Adaptee 类的对象:

public class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

在适配器类中,我们将 Adaptee 类的 specificRequest 方法转换成了 Target 接口的 request 方法。在 request 方法中,我们调用了 Adaptee 类的 specificRequest 方法,完成了适配过程。

接下来,我们就可以使用适配器类来适配 Adaptee 类的接口了:

public class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}

在客户端代码中,我们创建了一个 Adaptee 类的对象和一个适配器对象,并将适配器对象传递给客户端。当客户端调用 request 方法时,实际上是调用了适配器对象的 request 方法,这个方法又调用了 Adaptee 类的 specificRequest 方法,完成了适配过程。

适配器模式的优点在于它可以使现有的类与新的接口协同工作,而不需要修改现有的类。适配器模式也可以提高代码的复用性,可以将多个不同的类适配成同一个接口。适配器模式常用于系统间接口的兼容性问题,或者在开发过程中需要使用第三方库或框架的情况下,可以使用适配器模式来将第三方库或框架的接口适配成自己的接口。

在实际开发中,适配器模式也被广泛应用,下面是一些常见的应用场景和框架:

JDBC 框架

JDBC(Java Database Connectivity)是 Java 中操作数据库的标准接口,它定义了一套与数据库交互的规范,不同的数据库厂商实现了这个接口。在 JDBC 中,使用了适配器模式,通过适配器将 JDBC 接口适配成特定数据库厂商的接口,使得应用程序可以与不同的数据库交互,而不需要修改代码。

Spring MVC 框架

Spring MVC 是一个基于 Java 的 Web 开发框架,它使用了适配器模式来适配不同类型的请求和响应,以适应不同的 Web 容器和浏览器。

在 Spring MVC 中,DispatcherServlet 是一个适配器,它将客户端的请求适配成处理器的请求格式,并将处理器的响应适配成客户端的响应格式。这样,开发者就可以专注于处理器的开发,而不需要关心客户端的具体实现。

日志框架

在 Java 中,有许多不同的日志框架可供选择,如 Log4j、SLF4J 和 Logback 等。这些日志框架的接口不同,但它们都提供了类似的功能。在使用日志框架时,我们通常会使用适配器模式来适配不同的日志框架接口,以适应不同的项目需求。

总的来说,适配器模式是一种非常常用的设计模式,在实际开发中也有着广泛的应用。如果你需要将不兼容的接口适配成兼容的接口,或者需要使用第三方库或框架的接口,就可以使用适配器模式来实现。

接下来,我们将使用 Java 代码和注释的形式来详细讲解适配器模式的实现和应用。

实现

适配器模式包含三个角色:目标接口、适配器和被适配者。

目标接口

目标接口是我们的代码原有的接口,也就是我们期望的接口。在本例中,我们定义了一个 UserService 接口,其中包含了一些常见的用户操作方法,如新增用户、删除用户和更新用户等。

public interface UserService {
    void saveUser(User user);
    void deleteUser(User user);
    void updateUser(User user);
    User getUser(String id);
}

适配器

适配器是一个实现了目标接口的类,它包含了一个被适配者的实例。在本例中,我们将使用一个 UserRepository 类来充当被适配者,我们需要将它的接口适配成 UserService 接口。

public class UserRepositoryAdapter implements UserService {

    private UserRepository userRepository;

    public UserRepositoryAdapter(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void saveUser(User user) {
        userRepository.add(user);
    }

    @Override
    public void deleteUser(User user) {
        userRepository.remove(user);
    }

    @Override
    public void updateUser(User user) {
        userRepository.update(user);
    }

    @Override
    public User getUser(String id) {
        return userRepository.get(id);
    }
}

被适配者

被适配者是我们需要适配的接口或类。在本例中,我们定义了一个 UserRepository 接口,其中包含了一些常见的用户操作方法,如新增用户、删除用户和更新用户等。

public interface UserRepository {
    void add(User user);
    void remove(User user);
    void update(User user);
    User get(String id);
}

应用

下面我们将使用一个示例来说明适配器模式的应用。假设我们的应用程序需要在数据库中存储用户数据,我们可以使用 JDBC 来实现。

JDBC 接口

首先,我们定义了一个 JDBC 接口 JdbcService,它包含了一些常见的数据库操作方法,如连接数据库、查询数据和更新数据等。

public interface JdbcService {
    Connection getConnection();
    void execute(String sql);
    ResultSet executeQuery(String sql);
}

JDBC实现

我们使用了 H2 数据库来实现 JDBC 接口,下面是一个 H2 数据库的实现。

public class H2JdbcServiceImpl implements JdbcService {

    private final String driverClassName;
    private final String url;
    private final String username;
    private final String password;

    public H2JdbcServiceImpl(String driverClassName, String url, String username, String password) {
        this.driverClassName = driverClassName;
        this.url = url;
        this.username = username;
        this.password = password;
    }

    @Override
    public Connection getConnection() {
        try {
            Class.forName(driverClassName);
            return DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException | SQLException e){
            e.printStackTrace();
        }
    }
}

上面的代码中,我们实现了 JdbcService 接口,并使用 H2 数据库来连接数据库。我们的实现包括获取数据库连接、执行 SQL 语句和查询数据等操作。

适配器实现

现在,我们需要将 JdbcService 接口适配成 UserService 接口,以便我们可以将用户数据存储到数据库中。我们使用了 JdbcService 的实现类 H2JdbcServiceImpl 来充当被适配者,将它的接口适配成 UserService 接口。

public class JdbcUserRepositoryAdapter implements UserService {

    private final JdbcService jdbcService;

    public JdbcUserRepositoryAdapter(JdbcService jdbcService) {
        this.jdbcService = jdbcService;
    }

    @Override
    public void saveUser(User user) {
        Connection connection = jdbcService.getConnection();
        try {
            PreparedStatement statement = connection.prepareStatement("INSERT INTO user (id, name) VALUES (?, ?)");
            statement.setString(1, user.getId());
            statement.setString(2, user.getName());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void deleteUser(User user) {
        Connection connection = jdbcService.getConnection();
        try {
            PreparedStatement statement = connection.prepareStatement("DELETE FROM user WHERE id = ?");
            statement.setString(1, user.getId());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void updateUser(User user) {
        Connection connection = jdbcService.getConnection();
        try {
            PreparedStatement statement = connection.prepareStatement("UPDATE user SET name = ? WHERE id = ?");
            statement.setString(1, user.getName());
            statement.setString(2, user.getId());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public User getUser(String id) {
        Connection connection = jdbcService.getConnection();
        try {
            PreparedStatement statement = connection.prepareStatement("SELECT * FROM user WHERE id = ?");
            statement.setString(1, id);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                return new User(resultSet.getString("id"), resultSet.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

在适配器实现中,我们实现了 UserService 接口,并使用 JdbcService 的实现类 H2JdbcServiceImpl 来执行数据库操作。对于每个 UserService 接口的方法,我们都会获取一个数据库连接,并执行对应的 SQL 语句。

应用范例

适配器模式在许多框架中都有应用。下面是一些常见的框架和库,它们都使用了适配器模式来兼容其他框架和库。

  • JPA (Java Persistence API):JPA 是一个 Java 持久化框架,它允许开发者使用面向对象的方式来管理数据库操作。JPA 中提供了一些标准的 API,包括 EntityManager、EntityTransaction、Query 等。这些 API 可以适配不同的 ORM 框架,如 Hibernate、EclipseLink 等。
  • JDBC API:JDBC 是 Java 数据库连接 API,它提供了一组标准的接口和类,用于连接和操作数据库。在 JDBC 中,开发者可以使用不同的数据库驱动程序,如 MySQL、Oracle、SQL Server 等。
  • Spring JDBC:Spring JDBC 是 Spring Framework 中的一个模块,它提供了一些类和接口来简化 JDBC 编程。Spring JDBC 中的 JdbcTemplate 类就是使用了适配器模式,它可以将 JDBC 的 ResultSet 和 PreparedStatement 对象转换成对应的 Java 对象,从而简化了数据库操作。

以上是适配器模式在一些框架中的应用范例。适配器模式在实际应用中非常常见,特别是当我们需要将两个不兼容的接口或类整合在一起时。通过使用适配器模式,我们可以让这两个不兼容的接口或类能够一起工作,从而达到代码复用和解耦的目的。

你可能感兴趣的:(java,设计模式,适配器模式)