什么是策略模式:
我们创建表示各种策略的对象(超类)和一个行为随着策略对象改变而改变的具体对象(运行时),这种类型的设计模式属于行为型模式。
什么是工厂模式:
工厂模式是用来创建对象的一种最常用的设计模式。是用工厂方法代替new操作的一种模式。我们不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂。
业务场景:
用户生成订单需要调用支付接口,传统做法是if-else判断用户支付方式,调用不同的支付方式,这种做法无疑会造成大量的判断代码冗余,如果增加业务逻辑或新增支付方式需要修改代码,不利于代码的扩展性。
@Test
public void test01(){
Order order = new Order();
order.setName("张三");
order.setUid("00");
order.setOrderType("手机订单");
order.setPanymentType("zhifubao");
//实现支付
String resultPany = this.panymentByBuilder(order.getPanymentType());
System.out.println("resultPany = " + resultPany);
}
public String panymentByBuilder(String PanymentType){
if(PanymentType.equals("zhifubao")){
return "使用**支付宝**支付成功";
}else if(PanymentType.equals("weixin")){
return "使用**微信**支付成功";
}else if(PanymentType.equals("yinhangka")){
return "使用**银行卡**支付成功";
}else{
return "使用**现金**支付成功";
}
}
实际业务中,支付的代码逻辑是相当复杂的,存在调用各种API和使用各种工具,那么我们能不能将所有的支付方式都归集到一个类(超类),由不同的业务子类去实现编写不同的支付逻辑呢?最好还能把子类通过工厂Bean管理,我们需要什么子类就获取什么子类,策略模式+工厂模式就能完美解决这个问题
- 策略模式超类(抽象类):PaymentHandel
* 1.定义所有的业务逻辑性方法,也就是所有的支付方式
* 2.实现InitializingBean接口,初始化的时候将子类具体实现保存到bean工厂
/**
* 策略模式 业务逻辑的抽取
* @author zhangjiangfeng
* @version 14:43
*
* InitializingBean Stringboot bean初始化接口(自定义bean实例化)
*/
public abstract class PaymentHandel implements InitializingBean {
//支付方式
public void panymentType(){
throw new UnsupportedOperationException();
}
//支付来源
public void orderType(){
throw new UnsupportedOperationException();
}
}
- 子类实现PaymentHandel,拥有所有业务逻辑方法,和初始化bean接口
* 1.子类根据自身业务,实现部分业务逻辑代码功能
* 2.子类通过初始化bean接口,在初始化加载时将实例保存到bean工厂
/**
* @author zhangjiangfeng
* @version 15:23
*
*/
@Component
@Data
public class ZhiFuBao extends PaymentHandel{
@Override
public void panymentType() {
System.out.println("使用**支付宝**支付成功");
}
public void orderType(){
System.out.println("使用**手机**完成支付");
}
@Override
public void afterPropertiesSet() throws Exception {
FactoryBean.register("ZhiFuBao",this.getClass());
}
}
@Component
@Data
public class WeiXin extends PaymentHandel{
@Override
public void panymentType() {
System.out.println("使用**微信**支付成功");;
}
@Override
public void afterPropertiesSet() throws Exception {
FactoryBean.register("WeiXin",this.getClass());
}
}
- 工厂模式,用工厂方法代替new操作的一种模式。我们不暴露创建对象的具体逻辑
* 1.工厂模式提供regist方法,以K-V形式,保存bean实例 * 2.工厂模式提供get方法,根据参数K获取bean实例
**
* 工厂设计模式
* @author zhangjiangfeng
* @version 15:52
*
*/
@Component
public class FactoryBean {
private static Map<String, Class> HandelMap = new HashMap<>();
public static Class getHandel(String name){
return HandelMap.get(name);
}
public static void register(String name,Class tClass){
if(StringUtils.isNotBlank(name) && tClass!=null){
HandelMap.put(name,tClass);
}
}
}
现在我们通过策略模式+工厂模式调用支付接口,由此我们省略了大量的if-else代码块,同时如果需要新增支付方式或修改支付逻辑,我们只用对实现超类PaymentHandel的子类做相应的处理,这里也实现了java面向对象的开闭原则:只允许扩展不允许修改
@Test
public void test02() throws IllegalAccessException, InstantiationException {
//业务获取到用户订单数据
// Order order = new Order();
// order.setName("WeiXin");
// order.setUid("111");
// order.setOrderType("1");
// order.setPanymentType("1");
//由工厂bean返回对象实例,根据K获取的实例是zhifubao
Class<PaymentHandel> handel = FactoryBean.getHandel("ZhiFuBao");
PaymentHandel paymentHandel = handel.newInstance();
//调用实例方法
paymentHandel.panymentType();
}
2021-04-21 14:42:27.009 INFO 11612 --- [ main] c.z.studytest.StudyTestApplicationTests : Starting StudyTestApplicationTests using Java 1.8.0_181 on CTX-MCS-DEV023 with PID 11612 (started by zhangjiangfeng in C:\IDEAWorkSpace1\study-test)
2021-04-21 14:42:27.015 INFO 11612 --- [ main] c.z.studytest.StudyTestApplicationTests : No active profile set, falling back to default profiles: default
2021-04-21 14:42:28.587 INFO 11612 --- [ main] c.z.studytest.StudyTestApplicationTests : Started StudyTestApplicationTests in 2.281 seconds (JVM running for 4.818)
使用**支付宝**支付成功
Process finished with exit code 0
总结:
合理的运用设计模式,可以让我们的代码可读性,可维护性更好,设计模式是一种编程思想,并不是一成不变的模板,要切合实际业务去尝试使用设计模式。