Spring通过注解优雅实现工厂模式

发布于:2024-08-08 ⋅ 阅读:(78) ⋅ 点赞:(0)

Spring通过注解优雅实现工厂模式

工厂模式作为开发者,应该都是耳熟能详的,在课本上、在网络上都会有无数的案例,是一个简单、确十分好用的设计模式。但是实现它的方法有很多,早年见过最多的就是用 if 判断类型,然后返回不同的实现类。后来见过在数据库写上类型和实现类的对应关系,然后通过 getBean 动态获取。

讲实话从个人角度并不推荐这两种实现方式,方案一 :每次新增类型和实现类后还需要去对应工厂类新增映射关系,如果类型太多,看起来也很不优雅;方案二:大多数情况下所谓的灵活都是 伪需求,正常每个类型对应的实现类都是绑死的,一般不会去修改类型和实现类的对应关系,如果将这个关系维护到数据库中,就是为了一个 这辈子都用不上的所谓的灵活,我认为大可不必,这只会对代码阅读 带来更多的障碍。

不优雅的工厂

废话不多说,直接来看看目前见过的比较多的 不优雅 的工厂。

定义接口 DevelopmentEngineerService

public interface DevelopmentEngineerService {
    void writeCode(String codeDesc);
}

定义抽象类 AbstractDevelopmentEngineerService

@Slf4j
@Service
public abstract class AbstractDevelopmentEngineerService implements DevelopmentEngineerService{
    @Override
    public void writeCode(String codeDesc) {
        log.info("{} 实现了{},{}", getLevel(),codeDesc,getResult());
    }
    
    public abstract String getLevel();
    
    public abstract String getResult();

}

多态实现

LowDevelopmentEngineerService

@Service
public class LowDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "初级工程师:花费两天";
    }

    @Override
    public String getResult() {
        return "一堆BUG";
    }
}

MiddleDevelopmentEngineerService

@Service
public class MiddleDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "中级工程师:花费三天";
    }
    
    @Override
    public String getResult() {
        return "成功上线";
    }
}

HighDevelopmentEngineerService

@Service
public class HighDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "高级工程师:让中级工程师花费三天";
    }

    @Override
    public String getResult() {
        return "成功上线";
    }
}

工厂类 FactoryDevelopmentEngineerService

@Service
public class FactoryDevelopmentEngineerService {
    @Autowired
    private LowDevelopmentEngineerService lowDevelopmentEngineerService;
    @Autowired
    private MiddleDevelopmentEngineerService middleDevelopmentEngineerService;
    @Autowired
    private HighDevelopmentEngineerService highDevelopmentEngineerService;

    public DevelopmentEngineerService getDevelopmentEngineerService(String type) {
        if ("low".equals(type)){
            return lowDevelopmentEngineerService;
        } else if ("middle".equals(type)) {
            return middleDevelopmentEngineerService;
        }else if ("high".equals(type)){
            return highDevelopmentEngineerService;
        }else {
            throw new RuntimeException("开发工程师类型异常");
        }
    }
}

测试类与测试结果

public class DevelopmentEngineerServiceTest extends UicServiceApplicationTest {
    @Autowired
    private FactoryDevelopmentEngineerService developmentEngineerService;

    @Test
    public void writeCode(){
        developmentEngineerService.getDevelopmentEngineerService("low").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("middle").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("high").writeCode("用户注册/登录");
    }
}

在这里插入图片描述

对于以上代码,写的很好,实现了我们需要的功能、也成功的使用了工厂模式,但是我总觉得不够优雅,如果我的类型多达30个,那就要在上面注入30个对象,下面再写上一堆判断?是不是显得代码十分臃肿?

优雅的工厂模式

本质上SpringBoot的便捷和它对的 注解 的应用,是密不可分的。所以我们需要学会如何使用它。以带来更快地开发效率、更简介的代码行,以及看起来更加优雅的实现。

接口和抽象类不变 我就不重复贴代码了

多态实现

LowDevelopmentEngineerService

@Service("low")
public class LowDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "初级工程师:花费两天";
    }

    @Override
    public String getResult() {
        return "一堆BUG";
    }
}

MiddleDevelopmentEngineerService

@Service("middle")
public class MiddleDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "中级工程师:花费三天";
    }
    
    @Override
    public String getResult() {
        return "成功上线";
    }
}

HighDevelopmentEngineerService

@Service("high")
public class HighDevelopmentEngineerService extends AbstractDevelopmentEngineerService{
    @Override
    public String getLevel() {
        return "高级工程师:让中级工程师花费三天";
    }

    @Override
    public String getResult() {
        return "成功上线";
    }
}

注:这里 @Service注解里面有一个 value 属性,而此处则正是利用了这个 value 属性去进行标记

工厂类 FactoryDevelopmentEngineerService

@Service
public class FactoryDevelopmentEngineerService {
    // 根据类型注入 将DevelopmentEngineerService 的所有实现类都注入,map的key 就是 对应service顶部注解的 value 值
    @Autowired
    private Map<String, DevelopmentEngineerService> serviceMap = new ConcurrentHashMap<>();

    public DevelopmentEngineerService getDevelopmentEngineerService(String type) {
        DevelopmentEngineerService service = serviceMap.get(type);
        if (service == null) {
            throw new RuntimeException("开发工程师类型异常");
        }
        return service;
    }
}

通过这种实现方式我们可以确保 实现类和对应类型的映射关系维护在同一个Java 类文件中,并且无论如何新增/修改实现类都不需要再去调整工厂类。代码简介明了。

测试类与测试结果

public class DevelopmentEngineerServiceTest extends UicServiceApplicationTest {
    @Autowired
    private FactoryDevelopmentEngineerService developmentEngineerService;

    @Test
    public void writeCode(){
        developmentEngineerService.getDevelopmentEngineerService("low").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("middle").writeCode("用户注册/登录");
        developmentEngineerService.getDevelopmentEngineerService("high").writeCode("用户注册/登录");
    }
}

在这里插入图片描述