Java工厂模式与实战应用
一、工厂模式的本质思考
工厂模式本质上是在解决对象创建过程中的两个核心矛盾:
- 对象创建逻辑与业务逻辑的耦合:当业务代码直接new对象时,会与具体类产生强依赖
- 复杂对象的创建过程:某些对象的创建需要多步初始化操作或环境配置
我们来看一个典型反例:
public class OrderService {
public void createOrder() {
// 业务逻辑...
DatabaseLogger logger = new DatabaseLogger();
logger.log("Order created");
// 更多业务逻辑...
}
}
这种写法存在三个致命问题:
- 违反开闭原则:更换日志系统需要修改业务代码
- 难以测试:无法mock日志对象
- 职责混乱:业务类承担了对象创建职责
二、简单工厂模式的深度实现
简单工厂虽不在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();
}
}
这种模板方法+工厂方法的组合实现了:
- 创建逻辑与初始化逻辑分离
- 公共代码复用
- 子类专注具体实现
四、抽象工厂模式的现代实践
在现代微服务架构中,抽象工厂非常适合处理多环境配置。以多云适配为例:
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领域尤为明显:
- 保持跨平台代码一致性
- 快速切换云供应商
- 统一异常处理机制
五、工厂模式的性能优化策略
在大规模应用中,工厂的性能直接影响系统吞吐量。我们通过几种方式优化:
- 对象池化工厂:
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);
}
}
}
- 缓存工厂:
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);
}
});
}
}
- 并行化创建:
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));
}
}
七、工厂模式的测试策略
针对工厂的测试需要特别关注:
- 工厂方法测试:
public class LoggerFactoryTest {
@Test
void shouldCreateFileLogger() {
Logger logger = LoggerFactory.getLogger("file");
assertTrue(logger instanceof FileLogger);
}
@Test
void shouldThrowExceptionForInvalidType() {
assertThrows(IllegalArgumentException.class, () -> {
LoggerFactory.getLogger("invalid");
});
}
}
- 产品一致性测试:
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);
}
}
- 性能基准测试:
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
public class FactoryBenchmark {
@Benchmark
public void testCachedFactory() {
BeanFactory.getBean(MyService.class);
}
@Benchmark
public void testNewInstance() {
new MyService();
}
}
八、工厂模式的演进趋势
现代编程中的工厂模式呈现三个发展方向:
- 函数式工厂:
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();
}
}
- 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);
}
}
}
- 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);
}
// 动态编译加载...
}
九、工厂模式反模式警示
常见的错误用法包括:
- 过度工程化:为简单对象创建工厂
- 循环依赖:工厂与产品相互引用
- 类型爆炸:创建过多工厂类
正确做法评估表:
场景 | 推荐方案 | 理由 |
---|---|---|
对象创建简单 | 直接new | 避免过度设计 |
创建逻辑复杂 | 工厂方法 | 封装复杂初始化 |
需要产品族支持 | 抽象工厂 | 保证兼容性 |
需要动态扩展 | 反射+配置文件 | 实现运行时扩展 |
高频创建对象 | 对象池+缓存工厂 | 提升性能 |
十、工厂模式的替代方案
在某些场景下,其他模式可能更合适:
- 建造者模式:
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);
}
}
- 原型模式:
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();
}
}
- 依赖注入:
public class OrderService {
private final PaymentProcessor processor;
@Inject
public OrderService(PaymentProcessor processor) {
this.processor = processor;
}
}
正文到此结束
相关文章
热门推荐
评论插件初始化中...