Java工厂模式与实战应用

一、工厂模式的本质思考

工厂模式本质上是在解决对象创建过程中的两个核心矛盾:

  1. 对象创建逻辑与业务逻辑的耦合:当业务代码直接new对象时,会与具体类产生强依赖
  2. 复杂对象的创建过程:某些对象的创建需要多步初始化操作或环境配置

我们来看一个典型反例:

public class OrderService {
    public void createOrder() {
        // 业务逻辑...
        DatabaseLogger logger = new DatabaseLogger();
        logger.log("Order created");
        // 更多业务逻辑...
    }
}

这种写法存在三个致命问题:

  1. 违反开闭原则:更换日志系统需要修改业务代码
  2. 难以测试:无法mock日志对象
  3. 职责混乱:业务类承担了对象创建职责

二、简单工厂模式的深度实现

简单工厂虽不在GOF23种模式之列,但却是理解工厂模式的基石。我们通过配置文件+反射实现一个可扩展的增强版:

public class LoggerFactory {
    private static Map<String, Class<?>> loggerCache = new HashMap<>();

    static {
        // 加载配置文件
        Properties prop = new Properties();
        try (InputStream input = LoggerFactory.class.getClassLoader()
                .getResourceAsStream("logger.properties")) {
            prop.load(input);
            for (String key : prop.stringPropertyNames()) {
                Class<?> clazz = Class.forName(prop.getProperty(key));
                loggerCache.put(key, clazz);
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化日志工厂失败", e);
        }
    }

    public static Logger getLogger(String type) {
        try {
            Class<?> clazz = loggerCache.get(type);
            return (Logger) clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException("不支持的日志类型: " + type);
        }
    }
}

对应的配置文件logger.properties

fileLogger=com.example.FileLogger
databaseLogger=com.example.DatabaseLogger
cloudLogger=com.example.CloudLogger

这种实现方式的关键优势:

  • 新增日志类型只需修改配置文件
  • 通过类加载机制实现热注册
  • 利用缓存提升性能

三、工厂方法模式的进阶应用

当产品创建逻辑变得复杂时,工厂方法模式展现出真正的威力。以连接池创建为例:

public interface ConnectionPool {
    Connection getConnection();
    void releaseConnection(Connection conn);
    // 其他管理方法...
}

public abstract class ConnectionPoolFactory {
    public ConnectionPool createPool() {
        ConnectionPool pool = createConnectionPool();
        initializePool(pool);
        registerJMX(pool);
        return pool;
    }

    protected abstract ConnectionPool createConnectionPool();

    private void initializePool(ConnectionPool pool) {
        // 公共初始化逻辑
    }

    private void registerJMX(ConnectionPool pool) {
        // JMX注册逻辑
    }
}

public class MySQLPoolFactory extends ConnectionPoolFactory {
    @Override
    protected ConnectionPool createConnectionPool() {
        return new MySQLConnectionPool();
    }
}

public class OraclePoolFactory extends ConnectionPoolFactory {
    @Override
    protected ConnectionPool createConnectionPool() {
        return new OracleConnectionPool();
    }
}

这种模板方法+工厂方法的组合实现了:

  1. 创建逻辑与初始化逻辑分离
  2. 公共代码复用
  3. 子类专注具体实现

四、抽象工厂模式的现代实践

在现代微服务架构中,抽象工厂非常适合处理多环境配置。以多云适配为例:

public interface CloudResourceFactory {
    Storage createStorage();
    Compute createCompute();
    DNS createDNS();
}

public class AWSServiceFactory implements CloudResourceFactory {
    public Storage createStorage() {
        return new S3Storage();
    }
    
    public Compute createCompute() {
        return new EC2Compute();
    }
    
    public DNS createDNS() {
        return new Route53DNS();
    }
}

public class AzureServiceFactory implements CloudResourceFactory {
    // 类似实现Azure各组件
}

// 客户端代码
public class CloudDeployer {
    private CloudResourceFactory factory;
    
    public CloudDeployer(CloudResourceFactory factory) {
        this.factory = factory;
    }
    
    public void deploy() {
        Storage storage = factory.createStorage();
        Compute compute = factory.createCompute();
        DNS dns = factory.createDNS();
        
        // 部署逻辑...
    }
}

这种模式的优势在IoT领域尤为明显:

  • 保持跨平台代码一致性
  • 快速切换云供应商
  • 统一异常处理机制

五、工厂模式的性能优化策略

在大规模应用中,工厂的性能直接影响系统吞吐量。我们通过几种方式优化:

  1. 对象池化工厂
public class ThreadPoolFactory {
    private static final Map<String, ObjectPool<ExecutorService>> pools = new ConcurrentHashMap<>();

    public static ExecutorService getPool(String configKey) {
        return pools.computeIfAbsent(configKey, k -> {
            GenericObjectPoolConfig<ExecutorService> config = new GenericObjectPoolConfig<>();
            config.setMaxTotal(20);
            config.setMinIdle(5);
            return new GenericObjectPool<>(new ExecutorPooledObjectFactory(), config);
        }).borrowObject();
    }

    private static class ExecutorPooledObjectFactory extends BasePooledObjectFactory<ExecutorService> {
        @Override
        public ExecutorService create() {
            return Executors.newFixedThreadPool(10);
        }
    }
}
  1. 缓存工厂
public class BeanFactory {
    private static final ConcurrentMap<Class<?>, Object> singletonCache = new ConcurrentHashMap<>();
    
    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> clazz) {
        return (T) singletonCache.computeIfAbsent(clazz, k -> {
            try {
                return clazz.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException("实例化失败: " + clazz.getName(), e);
            }
        });
    }
}
  1. 并行化创建
public class ParallelFactory {
    private final ExecutorService executor = Executors.newWorkStealingPool();
    
    public <T> CompletableFuture<T> createAsync(Supplier<T> supplier) {
        return CompletableFuture.supplyAsync(supplier, executor);
    }
}

六、工厂模式在流行框架中的实战

Spring框架中的BeanFactory是工厂模式的集大成者。我们实现一个简化版:

public interface BeanFactory {
    Object getBean(String name);
    <T> T getBean(Class<T> requiredType);
}

public class AnnotationBeanFactory implements BeanFactory {
    private final Map<String, Object> beans = new ConcurrentHashMap<>();
    private final Map<Class<?>, String> typeMapping = new ConcurrentHashMap<>();

    public void scanPackages(String... basePackages) {
        // 使用反射扫描注解
        ClassPathScanningCandidateComponentProvider scanner = 
            new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
        
        for (String pkg : basePackages) {
            Set<BeanDefinition> candidates = scanner.findCandidateComponents(pkg);
            for (BeanDefinition candidate : candidates) {
                Class<?> clazz = Class.forName(candidate.getBeanClassName());
                registerBean(clazz);
            }
        }
    }

    private void registerBean(Class<?> clazz) {
        String beanName = resolveBeanName(clazz);
        Object instance = createInstance(clazz);
        beans.put(beanName, instance);
        typeMapping.put(clazz, beanName);
    }

    private Object createInstance(Class<?> clazz) {
        // 处理依赖注入
        Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
        Object[] args = Arrays.stream(constructor.getParameterTypes())
                .map(this::getBean)
                .toArray();
        return constructor.newInstance(args);
    }

    @Override
    public Object getBean(String name) {
        return beans.get(name);
    }

    @Override
    public <T> T getBean(Class<T> requiredType) {
        String name = typeMapping.get(requiredType);
        return requiredType.cast(beans.get(name));
    }
}

七、工厂模式的测试策略

针对工厂的测试需要特别关注:

  1. 工厂方法测试
public class LoggerFactoryTest {
    @Test
    void shouldCreateFileLogger() {
        Logger logger = LoggerFactory.getLogger("file");
        assertTrue(logger instanceof FileLogger);
    }

    @Test
    void shouldThrowExceptionForInvalidType() {
        assertThrows(IllegalArgumentException.class, () -> {
            LoggerFactory.getLogger("invalid");
        });
    }
}
  1. 产品一致性测试
public class ConnectionPoolTest {
    @Test
    void testPoolObjectConsistency() {
        ConnectionPoolFactory factory = new MySQLPoolFactory();
        ConnectionPool pool1 = factory.createPool();
        ConnectionPool pool2 = factory.createPool();
        
        assertNotSame(pool1, pool2);
        assertTrue(pool1.getClass() == MySQLConnectionPool.class);
    }
}
  1. 性能基准测试
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public class FactoryBenchmark {
    @Benchmark
    public void testCachedFactory() {
        BeanFactory.getBean(MyService.class);
    }

    @Benchmark
    public void testNewInstance() {
        new MyService();
    }
}

八、工厂模式的演进趋势

现代编程中的工厂模式呈现三个发展方向:

  1. 函数式工厂
public class PaymentFactory {
    private static final Map<String, Supplier<PaymentProcessor>> processors = Map.of(
        "alipay", AlipayProcessor::new,
        "wechat", WechatProcessor::new,
        "stripe", StripeProcessor::new
    );

    public static PaymentProcessor create(String type) {
        return processors.getOrDefault(type, 
            () -> { throw new IllegalArgumentException("无效支付类型"); })
            .get();
    }
}
  1. DSL式工厂
public class QueryFactory {
    public static QueryBuilder select(String... columns) {
        return new QueryBuilder().select(columns);
    }

    public static class QueryBuilder {
        private String[] columns;
        private String table;
        
        public QueryBuilder select(String... columns) {
            this.columns = columns;
            return this;
        }
        
        public QueryBuilder from(String table) {
            this.table = table;
            return this;
        }
        
        public Query build() {
            return new Query(String.join(",", columns), table);
        }
    }
}
  1. AI辅助工厂
public class AIGeneratedFactory {
    private static final Map<String, String> CODE_TEMPLATES = loadTemplates();
    
    public static Object create(String type, Map<String, Object> params) {
        String code = generateCode(type, params);
        return compileAndLoad(code);
    }
    
    private static String generateCode(String type, Map<String, Object> params) {
        String template = CODE_TEMPLATES.get(type);
        // 使用模板引擎替换参数
        return StrSubstitutor.replace(template, params);
    }
    
    // 动态编译加载...
}

九、工厂模式反模式警示

常见的错误用法包括:

  1. 过度工程化:为简单对象创建工厂
  2. 循环依赖:工厂与产品相互引用
  3. 类型爆炸:创建过多工厂类

正确做法评估表:

场景 推荐方案 理由
对象创建简单 直接new 避免过度设计
创建逻辑复杂 工厂方法 封装复杂初始化
需要产品族支持 抽象工厂 保证兼容性
需要动态扩展 反射+配置文件 实现运行时扩展
高频创建对象 对象池+缓存工厂 提升性能

十、工厂模式的替代方案

在某些场景下,其他模式可能更合适:

  1. 建造者模式
public class HttpClientBuilder {
    private int timeout = 5000;
    private int maxConnections = 10;
    private boolean gzipEnabled;
    
    public HttpClientBuilder timeout(int timeout) {
        this.timeout = timeout;
        return this;
    }
    
    public HttpClient build() {
        return new HttpClient(this);
    }
}
  1. 原型模式
public class PrototypeRegistry {
    private static final Map<String, Cloneable> prototypes = new HashMap<>();
    
    static {
        prototypes.put("defaultConfig", new AppConfig());
        prototypes.put("testConfig", new TestConfig());
    }
    
    public static AppConfig getConfig(String type) {
        return (AppConfig) prototypes.get(type).clone();
    }
}
  1. 依赖注入
public class OrderService {
    private final PaymentProcessor processor;
    
    @Inject
    public OrderService(PaymentProcessor processor) {
        this.processor = processor;
    }
}
正文到此结束
评论插件初始化中...
Loading...