工厂模式+策略模式 示例

工厂模式+策略模式 案例

1.案例背景

在我们实际项目开发中,设计模式往往不是单独使用的,多种设计模式的思想联合使用会使我们的代码看起来逻辑清晰,维护方便。下面就以一个支付方式的服务为案例,使用工厂模式+策略模式 做一个简单的演示。假设常用的支付方式有三种,分别为:微信支付(weChat)、支付宝支付(zfb)、银行卡支付(bankCard)。按我们常用的编码逻辑如下:

// 调用不同支付方式的逻辑
if ("weChat".equals("支付方式")) {
  payment("调用微信支付的服务");
} else if ("zfb".equals("支付方式")) {
  payment("调用支付宝支付的服务");
} else if ("bankCard".equals("支付方式")) {
  payment("调用银行卡宝支付的服务");
} else {
  payment("调用其它方式支付的服务");
}

上述代码在逻辑上并无问题,但是试想一下,这样的if else套了几十上百层、或者下次又有新的支付方式出现的时候,还得继续去改这部分代码,维护起来比较麻烦,我们希望接入新的支付方式后,不用改原来的代码,直接写我们新的支付方式的服务即可。下面就对此逻辑进行改造。

2.代码改造
2.1添加支付方式策略接口
/**
 * 支付策略接口
 */
public interface IPaymentStrategy {

    /**
     * 获取支付方式
     * @return
     */
    String getPayName();

    /**
     * 调用具体支付方法
     */
    void payMoney();
}
2.2 创建三种支付方式对支付方式策略接口进行实现
/**
 * 微信支付服务
 */
@Service
public class WeChatPaymentService implements IPaymentStrategy {
    @Override
    public String getPayName() {
        return "weChat";
    }

    @Override
    public void payMoney() {
        System.out.println("顾客选择的支付方式为: " + getPayName());
    }
}
/**
 * 支付宝支付服务
 */
@Service
public class ZfbPaymentService implements IPaymentStrategy {
    @Override
    public String getPayName() {
        return "zfb";
    }

    @Override
    public void payMoney() {
        System.out.println("顾客选择的支付方式为: " + getPayName());
    }
}
/**
 * 银行卡支付服务
 */
@Service
public class BankCardPaymentService implements IPaymentStrategy {

    @Override
    public String getPayName() {
        return "bankCard";
    }

    @Override
    public void payMoney() {
        System.out.println("顾客选择的支付方式为: " + getPayName());
    }
}
2.3 创建策略工厂,实现ApplicationContextAware接口
/**
 * 支付服务策略工厂
 */
@Component
public class PaymentFactory implements ApplicationContextAware {

    /**
     * 支付方式策略map
     */
    private static final Map<String, IPaymentStrategy> PAYMENT_STRATEGY_MAP = new ConcurrentHashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 返回实现IPaymentStrategy接口的策略bean
        Map<String, IPaymentStrategy> paymentBeanMap = applicationContext.getBeansOfType(IPaymentStrategy.class);
        paymentBeanMap.values().forEach(paymentBean -> {
            PAYMENT_STRATEGY_MAP.put(paymentBean.getPayName(), paymentBean);
        });
    }

    /**
     * 根据具体的支付方式获取对应的支付服务
     * @param paymentName 支付方式
     * @param 
     * @return
     */
    public <T extends IPaymentStrategy> IPaymentStrategy getPaymentInstance(String paymentName) {
        return PAYMENT_STRATEGY_MAP.get(paymentName);
    }
}
3.创建Controller进行测试
/**
 * 工厂策略支付controller
 */
@RestController
public class PaymentController {

    /**
     * 注入策略工厂
     */
    @Autowired
    private PaymentFactory paymentFactory;

    @GetMapping("/payment/{paymentName}")
    public Object payment(@PathVariable("paymentName") String paymentName) {
        IPaymentStrategy paymentInstance = paymentFactory.getPaymentInstance(paymentName);
        paymentInstance.payMoney();
        return paymentInstance.getPayName() + "支付成功!";
    }
}

浏览器输入:http://localhost:端口号/payment/支付方式(weChat/zfb/bankCard) 查看访问结果。

4.拓展

策略工厂的另外一种实现方式

/**
 * 支付服务策略工厂
 */
@Component
public class PaymentStrategyFactory {

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 支付方式策略map
     */
    private static final Map<String, IPaymentStrategy> PAYMENT_STRATEGY_MAP = new ConcurrentHashMap<>();

    /**
     * 自动装载入spring容器中
     * @return
     */
    @Bean
    public Map<String, IPaymentStrategy> getPaymentStrategyMap() {
        // 返回实现IPaymentStrategy接口的策略bean
        Map<String, IPaymentStrategy> paymentBeanMap = applicationContext.getBeansOfType(IPaymentStrategy.class);
        paymentBeanMap.values().forEach(paymentBean -> {
            PAYMENT_STRATEGY_MAP.put(paymentBean.getPayName(), paymentBean);
        });
        return PAYMENT_STRATEGY_MAP;
    }

    /**
     * 根据具体的支付方式获取对应的支付服务
     * @param paymentName 支付方式
     * @param 
     * @return
     */
    public <T extends IPaymentStrategy> IPaymentStrategy getPaymentInstance(String paymentName) {
        return PAYMENT_STRATEGY_MAP.get(paymentName);
    }

}

@RestController
public class PaymentController {

    @Autowired
    private PaymentStrategyFactory paymentStrategyFactory;

    @GetMapping("/paymentStrategy/{paymentName}")
    public Object paymentStrategy(@PathVariable("paymentName") String paymentName) {
        IPaymentStrategy paymentInstance = paymentStrategyFactory.getPaymentInstance(paymentName);
        paymentInstance.payMoney();
        return paymentInstance.getPayName() + "支付成功!";
    }
}
5.总结

用工厂模式+策略模式对代码逻辑进行改造的优缺点:
优点:代码清爽,符合开闭原则,不必改造原来的代码,代码的扩展性强;
缺点:每种支付方式需要创建一个实现类,代码略显膨胀。

你可能感兴趣的:(设计模式,策略模式,java,开发语言,简单工厂模式)