工厂模式
基本介绍
核心思想:不直接在业务代码里 new 对象,而是把对象创建过程交给一个 “工厂类” 统一管理
这样做的好处是:业务代码不关心具体创建哪个实现类,只关心拿到一个可用对象
业务场景:一个业务中有很多不同的类型,每个类型都有自己对应的逻辑,使用 if - else 判断会显得代码冗长,且后续新增类型也不好维护,工厂模式可以把这些对象创建逻辑集中起来
优点如下
(1)对象创建逻辑集中管理
(2)业务代码不需要直接依赖具体实现类
(3) 新增实现类时,修改范围更可控
(4) 降低代码耦合度
缺点如下
(1)每次新增类型,通常都要修改工厂类
(2)如果类型很多,工厂类会越来越复杂
(3)简单工厂不完全符合开闭原则:对扩展开放,对修改关闭
标准工厂模式
实现思路
定义接口,编写不同的实现类去实现接口,并实现具体的业务逻辑,后续扩展只需要新增实现类即可
编写工厂模式,返回不同实现类的对象实例,用接口接收,利用 Java 的多态特性,实现方法的调用
代码示例
(1)定义接口
java
public interface PayService {
void pay(BigDecimal amount);
}(2)定义不同的实现类
java
public class AliPayService implements PayService {
@Override
public void pay(BigDecimal amount) {
System.out.println("使用支付宝支付:" + amount);
}
}
public class WeChatPayService implements PayService {
@Override
public void pay(BigDecimal amount) {
System.out.println("使用微信支付:" + amount);
}
}(3)定义工厂类
java
public class PayServiceFactory {
public static PayService getPayService(String payType) {
if ("ALI_PAY".equals(payType)) {
return new AliPayService();
}
if ("WECHAT_PAY".equals(payType)) {
return new WeChatPayService();
}
if ("BANK_CARD".equals(payType)) {
return new BankCardPayService();
}
throw new IllegalArgumentException("不支持的支付类型:" + payType);
}
}(4)应用示例
java
public class OrderService {
public void payOrder(String payType, BigDecimal amount) {
PayService payService = PayServiceFactory.getPayService(payType);
payService.pay(amount);
}
}简单工厂 + 策略映射
需求分析
需要根据不同的锁类型创建不同的锁对象,且由用户传参动态选择
代码实现
思路分析:先定义一个枚举类,声明所有的类型,之后通过工厂模式声明并创建对象返回,后续业务中无需关注创建什么对象,只需要专注于如何拿到某个对象
(1)定义枚举类
java
public enum MyLockType {
RE_ENTRANT_LOCK,
FAIR_LOCK,
READ_LOCK,
WRITE_LOCK,
;
}(2)定义工厂类
MyLockFactory 内部持有了一个 Map,key 是锁类型枚举,值是创建锁对象的 Function,注意这里不是存锁对象,因为锁对象必须是多例的,不同业务用不同锁对象,同一个业务用相同锁对象
MyLockFactory 内部的 Map 采用了 EnumMap,只有当 Key 是枚举类型时可以使用 EnumMap,其底层不是 hash 表,而是简单的数组,由于枚举项数量固定,因此这个数组长度就等于枚举项个数,然后按照枚举项序号作为角标依次存入数组。这样就能根据枚举项序号作为角标快速定位到数组中的数据
java
@Component
public class MyLockFactory {
private final Map<MyLockType, Function<String, RLock>> lockHandlers;
public MyLockFactory(RedissonClient redissonClient) {
this.lockHandlers = new EnumMap<>(MyLockType.class);
this.lockHandlers.put(RE_ENTRANT_LOCK, redissonClient::getLock);
this.lockHandlers.put(FAIR_LOCK, redissonClient::getFairLock);
this.lockHandlers.put(READ_LOCK, name -> redissonClient.getReadWriteLock(name).readLock());
this.lockHandlers.put(WRITE_LOCK, name -> redissonClient.getReadWriteLock(name).writeLock());
}
public RLock getLock(MyLockType lockType, String name){
return lockHandlers.get(lockType).apply(name);
}
}(3)应用示例
java
@RequiredArgsConstructor
public class MyLockAspect {
private final MyLockFactory lockFactory;
public Object tryLock(MyLock myLock) {
// 通过工厂模式创建锁对象
RLock lock = lockFactory.getLock(myLock.lockType(), myLock.name());
}
}
// MyLock 是一个注解,定义了一些属性
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyLock {
String name();
long waitTime() default 1;
long leaseTime() default -1;
TimeUnit unit() default TimeUnit.SECONDS;
MyLockType lockType() default MyLockType.RE_ENTRANT_LOCK;
MyLockStrategy lockStrategy() default MyLockStrategy.FAIL_AFTER_RETRY_TIMEOUT;
}