设计模式: 工厂方法模式(Factory Method Pattern) + 策略模式(Strategy Pattern)
目录
基础概念
工厂方法模式(Factory Method Pattern)
也被称为多态工厂模式,其定义了一个创建某种产品的接口,但由子类决定要实例化的产品是哪一个,从而把产品的实例化推迟到子类
策略模式(Strategy Pattern)
定义了一组策略,分别在不同类中封装起来,每种策略都可以根据当前场景相互替换,从而使策略的变化可以独立于操作者。
使用场景
工厂模式一般配合策略模式一起使用,当系统中有多种产品(策略),且每种产品有多个实例时,此时适合使用工厂模式:每种产品对应的工厂提供该产品不同实例的创建功能,从而避免调用方和产品创建逻辑的耦合,完美符合迪米特法则(最少知道原则)。
定义抽象产品(策略)
public interface Strategy<T> {
    /**
     * Get identify
     *
     * @return ID
     */
    T getId();
}
定义抽象策略工厂
通过组合方式将引入当前工厂中的产品(策略)类型
public class StrategyFactory<T, S extends Strategy<T>> implements InitializingBean, ApplicationContextAware {
    private Map<T, S> strategyFactory;
    private final Class<S> strategyType;
    private ApplicationContext context;
    /**
     * Get Strategy by id
     *
     * @param id identify of strategy
     * @return strategy
     */
    public S getStrategy(T id) {
        return strategyFactory.get(id);
    }
    /**
     * Strategy type
     *
     * @return type of strategy
     */
    protected Class<S> getStrategyType() {
        return this.strategyType;
    }
    public StrategyFactory(Class<S> strategyType) {
        this.strategyType = strategyType;
    }
    @Override
    public void afterPropertiesSet() {
        Collection<S> values = context.getBeansOfType(getStrategyType()).values();
        strategyFactory = Maps.newHashMapWithExpectedSize(values.size());
        values.forEach(item -> strategyFactory.put(item.getId(), item));
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}
业务实战
定义策略
public interface PaymentTypeStrategy extends Strategy<String> {
    /**
     * Get payment type
     *
     * @return payment type
     */
    String getPaymentType();
    /**
     * Do pay
     */
    void doPay();
    /**
     * Get id of Payment Type
     *
     * @return ID
     */
    @Override
    default String getId() {
        return getPaymentType();
    }
}
放入Spring容器
@Configuration
public class StrategyFactoryConfig {
    @Bean
    public StrategyFactory<String, PaymentTypeStrategy> getPaymentTypeFactory() {
        return new StrategyFactory<>(PaymentTypeStrategy.class);
    }
}
具体业务实现
CASE 1:
@Component
@Slf4j
public class PayByStripeStrategy implements PaymentTypeStrategy {
    @Override
    public String getPaymentType() {
        return "Stripe";
    }
    @Override
    public void doPay() {
        log.info("Start pay by: {}", getPaymentType());
    }
}
CASE 2:
@Component
@Slf4j
public class PayByCheckoutStrategy implements PaymentTypeStrategy {
    @Override
    public String getPaymentType() {
        return "Checkout";
    }
    @Override
    public void doPay() {
        log.info("Start pay by: {}", getPaymentType());
    }
}
测试
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {StrategyFactoryConfig.class, PayByStripeStrategy.class, PayByCheckoutStrategy.class})
public class PaymentTypeStrategyTest {
    @Resource
    private StrategyFactory<String, PaymentTypeStrategy> factory;
    @Test
    public void testStripePayStrategy() {
        PaymentTypeStrategy strategy = factory.getStrategy("Stripe");
        strategy.doPay();
    }
14:25:38.946 [main] INFO com.th.test.pattern.strategy.paymenttype.impl.PayByStripeStrategy - Start pay by: Stripe

                
            
        
浙公网安备 33010602011771号