策略模式+工厂模式代替if else 循环

1.为什么要使用策略模式+工厂类实现
   虽说这种模式看起来十分优雅,但是不可否认多写了接口,工厂类,以及N多个实现类具体类造成编码等成本,但是就ielse if...业务代码很长(原谅我没文化啊)代码的维护将变得十分困难,光这一点就值得使用模式优化了

2.讨论
   个人觉得使用工厂类+反射注入实际解决问题的实现类特好,但是我没有完美解决该问题.如下代码所示

​
    public static StrategyService getStrategyImpl(String strategyType) throws Exception {
        /*
         * getStrategyImpl():  是通过反射+枚举类(valueOf())获取类全路径
         * StrategyService: 为我抽取的接口
         * StatusEnum: 枚举类
         *
         * */
        String className = StatusEnum.valueOf(strategyType).getClassName();
        return (StrategyService) Class.forName(className).newInstance();
    }

​


该工厂类使用反射newInstance(),方法在本质上和使用枚举类 new 实现类一样,但是 new 后就不归属于 spring 容器管理了,这就造成了我在实现类中在使用其他serviceImpl实现类或者dao调用数据保存出现注入的值本身是null.也不是没有解决的方法这不是说本质上我没有获取的spring上管理的bean呗,所以跳过new的实例,直接获取spring容器中的Bean是否可行?
先创建springUtil方法

@Component
public class BeanUtils implements ApplicationContextAware {

    protected static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        if (applicationContext == null) {
            applicationContext = arg0;
        }

    }

    public static Object getBean(String name) {
        //name表示其他要注入的注解name名
        return applicationContext.getBean(name);
    }

    /**
     * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

再然后在实现类中手动获取bean如下,BeanUtils.getBean(TestApi.class)方法获取实现类bean在执行testApi的新增方法.这种方法虽说实现了要求但是每次调用方法都会调用getBean()方法去获取对象比较耗费资源.

@Slf4j
@Service
public class LoopCoordinateMethodImpl extends LoopMethodAbstract {

    @Override
    public <T> int runAppointed(List<T> lists, String channelName) {
        List<User> list = (User) lists;
        TestApi testApi = BeanUtils.getBean(TestApi.class);
        return testApi.updateBatch(list);
    }

}

3.实现
  再说说另一种方法如何实现,上述核心问题还是工厂类提供的接口实现类是new的而不是注入的呗.
 3.1 抽取接口
 

public interface ILoopMethodService {
    <T> int runAppointed(List<T> list);
}

3.2  实现类

@Service
@Slf4j
public class LoopMethodImpl implements ILoopMethodService {

    @Autowired
    private TestApi testApi;

    @Override
    public <T> int runAppointed(List<T> lists) {
        System.out.println("本身的方法逻辑执行了...");
        System.out.println("lists = " + lists.toString());
        testApi.test01();
        return 0;
    }
}

3.3 另一个不实现该功能接口的实现类(验证)

@Slf4j
@Service
public class TestApi {

    public void test01(){
        System.out.println("调用的方法执行了...");
    }
}

3.4 工厂类

@Component
@Slf4j
public class LoopTypeFactory {

    @Autowired
    private LoopMethodImpl loopCoordinateMethod;

    public ILoopMethodService getLoopMethodImpl(String channelName) {
        Map<String, ILoopMethodService> map = new HashMap<>(16);
        map.put(LoopMethodEnum.COORDINATE_LOOP.channelName, loopCoordinateMethod);
        ILoopMethodService iLoopMethodService = map.get(channelName);
        if (iLoopMethodService == null){
            log.error("抛出异常");
        }
        return iLoopMethodService;
    }
}

3.5 一个简单的枚举类

public enum LoopMethodEnum {

    /*
     *
     * */
    CUST_LOOP("TEST"),
    /*
     * 兜底默认未知方法
     * */
    UNKNOWN("DEFINE"),

    /*
     *  测试的方法
     * */
    COORDINATE_LOOP("RUN");

    public String channelName;//处理方法代号

    LoopMethodEnum(String channelName) {
        this.channelName = channelName;
    }

}

3.6 测试Controller
 

@RestController
@Slf4j
public class TestController {

    @Autowired
    private LoopTypeFactory loopTypeFactory;

    @PostMapping("/test02")
    public void test66(@RequestBody String parameters) {
        List<Object> list = new ArrayList<>();
        list.add("12121");
        list.add("12122");
        list.add("12123");
        list.add("12124");
        ILoopMethodService coordinate = loopTypeFactory.getLoopMethodImpl(LoopMethodEnum.COORDINATE_LOOP.channelName);
        coordinate.runAppointed(list);
    }
}

测试结果如下

使用该种方法需要在新增实体类的时候需要修改工厂类添加实体类,所以有没有知道如果使用反射来封装但是可以在后续仍然可以使用注入类的方法,如果知道若能告知在下将感激不尽!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值