在我们实际项目开发中,设计模式往往不是单独使用的,多种设计模式的思想联合使用会使我们的代码看起来逻辑清晰,维护方便。下面就以一个支付方式的服务为案例,使用工厂模式+策略模式 做一个简单的演示。假设常用的支付方式有三种,分别为:微信支付(weChat)、支付宝支付(zfb)、银行卡支付(bankCard)。按我们常用的编码逻辑如下:
// 调用不同支付方式的逻辑
if ("weChat".equals("支付方式")) {
payment("调用微信支付的服务");
} else if ("zfb".equals("支付方式")) {
payment("调用支付宝支付的服务");
} else if ("bankCard".equals("支付方式")) {
payment("调用银行卡宝支付的服务");
} else {
payment("调用其它方式支付的服务");
}
上述代码在逻辑上并无问题,但是试想一下,这样的if else套了几十上百层、或者下次又有新的支付方式出现的时候,还得继续去改这部分代码,维护起来比较麻烦,我们希望接入新的支付方式后,不用改原来的代码,直接写我们新的支付方式的服务即可。下面就对此逻辑进行改造。
/**
* 支付策略接口
*/
public interface IPaymentStrategy {
/**
* 获取支付方式
* @return
*/
String getPayName();
/**
* 调用具体支付方法
*/
void payMoney();
}
/**
* 微信支付服务
*/
@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());
}
}
/**
* 支付服务策略工厂
*/
@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);
}
}
/**
* 工厂策略支付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) 查看访问结果。
策略工厂的另外一种实现方式
/**
* 支付服务策略工厂
*/
@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() + "支付成功!";
}
}
用工厂模式+策略模式对代码逻辑进行改造的优缺点:
优点:代码清爽,符合开闭原则,不必改造原来的代码,代码的扩展性强;
缺点:每种支付方式需要创建一个实现类,代码略显膨胀。