现象 大量的分支选择型代码段看着让人头疼
for (Field field : declaredFields) { Class<?> type = field.getType(); String key = field.getName(); Element result = resultMap.addElement("result"); result.addAttribute("column", StringChangeUtils.CamelhumpToUnderline(key).toLowerCase()); result.addAttribute("property", key); switch (type.getSimpleName()) { case "String": result.addAttribute("jdbcType", "VARCHAR"); break; case "Integer": result.addAttribute("jdbcType", "NUMERIC"); break; case "Double": result.addAttribute("jdbcType", "NUMERIC"); break; case "Date": result.addAttribute("jdbcType", "DATE"); break; default: result.addAttribute("jdbcType", "VARCHAR"); break; } }
如何重构成为策略模式,由硬编码的面向过程编程走向面对对象呢
其实很简单 if里面的多个魔法常量 和HashMap里面的key是不是可以等比互换呢!!
所以我们核心就是从一个类似于HashMap这种的容器里去获取某一个key,就等同于进去到了if 的对应分支
而if 的对应分支 里面的业务,交给HashMap的Value去调方法完成没毛病把
第一步抽象化这个if分支的逻辑 ---- 分析
--比如上述代码是判断字段类型 --->通用对象接口是对象类型的·抽象·
-- 那么这个对象具有什么能力,就是对应原始if分支的逻辑处理 呗,,
-- 我这里是根据不同的字段类型往一个Element元素对象中填充属性。 -----所以抽出行为为往Element元素对象中填充属性
第二步抽象化这个if分支的逻辑----- 实现
public interface FileTypeInterfaceStrategy { void addAttribute(Element element); }
第三步抽象if分支的种类,不同种类有不同实现,-----分析
1. 比如 类型抽象 有String 类型 2. 比如 类型抽象 有Double 类型 3. 比如 类型抽象 有DATE 类型 4. 等等。。。。。
第四步抽象if分支的种类,不同种类有不同实现,-----实现
- 比如 类型抽象 有String 类型 实现
public class StringStrategy implements FileTypeInterfaceStrategy { @Override public void addAttribute(Element element) { element.addAttribute("jdbcType", "VARCHAR"); } }
- 比如 类型抽象 有Integer 类型 实现
public class IntegerStrategy implements FileTypeInterfaceStrategy { @Override public void addAttribute(Element element) { element.addAttribute("jdbcType", "NUMERIC"); } }
- 比如 类型抽象 有Double 类型 实现
public class DoubleStrategy implements FileTypeInterfaceStrategy { @Override public void addAttribute(Element element) { element.addAttribute("jdbcType", "NUMERIC"); } }
- 比如 类型抽象 有Date 类型 实现
public class DateStrategy implements FileTypeInterfaceStrategy { @Override public void addAttribute(Element element) { element.addAttribute("jdbcType", "DATE"); } }
- 比如 类型抽象 有其他 类型 实现
public class DefaultStrategy implements FileTypeInterfaceStrategy { @Override public void addAttribute(Element element) { element.addAttribute("jdbcType", "VARCHAR"); } }
第五步if分支的过程编程已经抽离为对象行为编程----目前如何嵌入业务分析
思考 if选择分支,第一件事是不是拿到一个值去判断属于某一个魔法常量呢! 其实 抽离成对象之后业同理需要知道,这里的上文行为需要下文的那一个对象的实现去处理。。 比如,上文中拿到String、类型,我需要使用String类型的实现类去调业务方法。 比如,上文中拿到Integer、类型,我需要使用Integer类型的实现类去调业务方法。
if的分支属性和业务行为被抽离成对象--但是还有个东西没有抽离,就是IF本身的分支选择结构没抽出来 对不对
这时候联想到第一句话:if本身业务结构还需要抽离-----它本身和HashMaP这种结构类似 是不是可以用它完成替换
第六步if分支的过程编程已经抽离为对象行为编程----目前如何嵌入业务实现
使用工厂方法代理策略的选择执行:其实很简单,就是new 一个HashMap,然后把所有的策略对象和Key放入HashMap,使用时候去容器里面取出来执行业务方法就完事
public class FileTypeStrategyFactory { private FileTypeStrategyFactory() { } private static final FileTypeStrategyFactory bean = new FileTypeStrategyFactory(); public static FileTypeStrategyFactory getBean() { return bean; } /** * 声明存储容器 */ private static Map<String, FileTypeInterfaceStrategy> factoryMap; static { factoryMap = new HashMap<>(); factoryMap.put("String", new StringStrategy()); factoryMap.put("Integer", new IntegerStrategy()); factoryMap.put("Double", new DoubleStrategy()); factoryMap.put("Date", new DateStrategy()); factoryMap.put("default", new DefaultStrategy()); } public FileTypeInterfaceStrategy getStrategy(String classType) { return factoryMap.get(classType) != null ? factoryMap.get(classType) : factoryMap.get("default"); } }
替换原始代码;
Element resultMap = document.addElement("resultMap"); // 添加根节点属性 resultMap.addAttribute("id", aClass.getSimpleName() + "Map"); resultMap.addAttribute("type", classForName); resultMap.addAttribute("extends", "BaseResultMap"); for (Field field : declaredFields) { Class<?> type = field.getType(); String key = field.getName(); Element result = resultMap.addElement("result"); result.addAttribute("column", StringChangeUtils.CamelhumpToUnderline(key).toLowerCase()); result.addAttribute("property", key); FileTypeStrategyFactory factory = FileTypeStrategyFactory.getBean(); FileTypeInterfaceStrategy strategy = factory.getStrategy(type.getSimpleName()); strategy.addAttribute(result); }