首页 云计算

告别硬编码:用抽象工厂模式优雅管理你的产品家族

分类:云计算
字数: (5834)
阅读: (9546)
内容摘要:告别硬编码:用抽象工厂模式优雅管理你的产品家族,

假设我们正在开发一个电商系统,需要支持多种数据库,比如 MySQL 和 PostgreSQL。最初,我们的代码可能到处都是 if...else 判断,根据配置选择不同的数据库连接、SQL 语句等等。这种方式不仅代码臃肿,而且可维护性极差。每增加一种数据库,都要修改大量的代码,测试压力巨大。这种硬编码的方式显然无法应对未来的变化。

这时,抽象工厂模式就派上用场了。它可以帮助我们创建一个产品家族,而无需指定具体的类。

告别硬编码:用抽象工厂模式优雅管理你的产品家族

抽象工厂模式深度剖析

抽象工厂模式属于创建型设计模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。它的核心思想是将一组产品的创建封装到一个工厂中,客户端通过工厂来获取产品,而无需关心产品的具体实现。

告别硬编码:用抽象工厂模式优雅管理你的产品家族

模式结构

  • 抽象工厂 (Abstract Factory):声明一组用于创建抽象产品的接口。
  • 具体工厂 (Concrete Factory):实现抽象工厂接口,创建具体的产品对象。
  • 抽象产品 (Abstract Product):声明产品对象的接口。
  • 具体产品 (Concrete Product):实现抽象产品接口,定义具体的产品。
  • 客户端 (Client):使用抽象工厂和抽象产品提供的接口。

工作原理

  1. 客户端通过具体工厂来创建产品家族。
  2. 具体工厂根据客户端的需求,创建相应的具体产品。
  3. 客户端使用抽象产品接口来操作产品,而无需关心产品的具体实现。

代码实战:MySQL 和 PostgreSQL 的支持

现在我们用 Java 代码来实现一个简单的示例,支持 MySQL 和 PostgreSQL 数据库。

告别硬编码:用抽象工厂模式优雅管理你的产品家族
// 抽象产品:数据库连接接口
interface Connection {
    void connect();
}

// 具体产品:MySQL 连接
class MySQLConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("Connecting to MySQL...");
    }
}

// 具体产品:PostgreSQL 连接
class PostgreSQLConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("Connecting to PostgreSQL...");
    }
}

// 抽象产品:数据库命令接口
interface Command {
    void execute(String sql);
}

// 具体产品:MySQL 命令
class MySQLCommand implements Command {
    @Override
    public void execute(String sql) {
        System.out.println("Executing MySQL command: " + sql);
    }
}

// 具体产品:PostgreSQL 命令
class PostgreSQLCommand implements Command {
    @Override
    public void execute(String sql) {
        System.out.println("Executing PostgreSQL command: " + sql);
    }
}

// 抽象工厂:数据库工厂接口
interface DatabaseFactory {
    Connection createConnection();
    Command createCommand();
}

// 具体工厂:MySQL 工厂
class MySQLFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new MySQLConnection();
    }

    @Override
    public Command createCommand() {
        return new MySQLCommand();
    }
}

// 具体工厂:PostgreSQL 工厂
class PostgreSQLFactory implements DatabaseFactory {
    @Override
    public Connection createConnection() {
        return new PostgreSQLConnection();
    }

    @Override
    public Command createCommand() {
        return new PostgreSQLCommand();
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 使用 MySQL 工厂
        DatabaseFactory mysqlFactory = new MySQLFactory();
        Connection mysqlConnection = mysqlFactory.createConnection();
        Command mysqlCommand = mysqlFactory.createCommand();
        mysqlConnection.connect();
        mysqlCommand.execute("SELECT * FROM users");

        // 使用 PostgreSQL 工厂
        DatabaseFactory postgresqlFactory = new PostgreSQLFactory();
        Connection postgresqlConnection = postgresqlFactory.createConnection();
        Command postgresqlCommand = postgresqlFactory.createCommand();
        postgresqlConnection.connect();
        postgresqlCommand.execute("SELECT * FROM users");
    }
}

配置方案 (示例:Spring Boot + 多数据源)

在 Spring Boot 项目中,可以结合 @ConfigurationProperties@Bean 注解,将数据库配置信息注入到工厂类中。例如:

告别硬编码:用抽象工厂模式优雅管理你的产品家族
@Configuration
public class DatabaseConfig {

    @ConfigurationProperties(prefix = "mysql")
    @Bean
    public DataSource mysqlDataSource() { // 使用 HikariCP 连接池
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @ConfigurationProperties(prefix = "postgresql")
    @Bean
    public DataSource postgresqlDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean
    @Primary // 优先使用 MySQL
    public JdbcTemplate jdbcTemplate(DataSource mysqlDataSource) {
        return new JdbcTemplate(mysqlDataSource);
    }

    @Bean(name = "postgresqlJdbcTemplate")
    public JdbcTemplate postgresqlJdbcTemplate(DataSource postgresqlDataSource) {
        return new JdbcTemplate(postgresqlDataSource);
    }

}

在 application.yml 或 application.properties 中配置数据库连接信息:

mysql:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password
postgresql:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: postgres
    password: password

实战避坑经验总结

  • 过度设计:不要为了使用抽象工厂模式而使用,只有在确实需要创建产品家族时才考虑它。如果只有单个产品,简单工厂模式可能更合适。
  • 接口膨胀:抽象工厂的接口应该足够通用,但也需要避免过于庞大,导致实现类难以维护。可以考虑使用多个小的抽象工厂接口,然后组合它们。
  • 依赖注入:在大型项目中,可以使用依赖注入框架(如 Spring)来管理工厂类的创建和依赖关系,避免手动创建工厂对象。
  • 扩展性考虑:在使用抽象工厂模式时,要考虑到未来的扩展性。如果需要增加新的产品,应该尽量避免修改现有的代码,而是通过新增具体工厂和具体产品来实现。
  • 并发安全:在多线程环境下,需要注意工厂类的并发安全问题,避免多个线程同时创建产品对象导致数据不一致。可以使用线程安全的集合或者同步机制来保证并发安全。

通过使用抽象工厂模式,我们可以将数据库的创建和使用解耦,使得代码更加灵活、可维护和可扩展。无论未来需要支持多少种数据库,我们都可以通过新增具体工厂来实现,而无需修改现有的代码。这大大提高了系统的稳定性和可维护性。

告别硬编码:用抽象工厂模式优雅管理你的产品家族

转载请注明出处: 键盘上的咸鱼

本文的链接地址: http://m.acea1.store/blog/592847.SHTML

本文最后 发布于2026-04-22 00:18:24,已经过了5天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 海带缠潜艇 1 天前
    楼主讲得很透彻,结合了 Spring Boot 的配置方案,更贴近实际项目,赞一个!
  • 武汉热干面 4 天前
    写得真不错,解决了我在多数据库支持上的痛点,之前的 if else 地狱简直是噩梦!
  • 秋名山车神 2 天前
    写得真不错,解决了我在多数据库支持上的痛点,之前的 if else 地狱简直是噩梦!
  • 蛋炒饭 2 天前
    代码示例很清晰,可以直接拿来用了,感谢分享! 不过如果能加上错误处理就更完美了。