参考:
https://www.shuzhiduo.com/A/ke5jZwbO5r/
https://blog.csdn.net/Li_haiyu/article/details/124341345
工厂方法是我们实际工作中经常用到的。
比如下面的例子,一个接口有多个实现类,我们自然而然会想到使用工厂方法。
//接口类 public interface ReportService { String getResult(); } //实现类 public class ReportServiceA1 implements ReportService { @Override public String getResult() { return "我是A1"; } } //实现类 public class ReportServiceA2 implements ReportService { @Override public String getResult() { return "我是A2"; } }
为了构造实现类的实例,我们创建一个工厂类
public class ReportFactory { public static ReportService createService(String name){ if(name.equals("A1")){ return new ReportServiceA1(); }else if(name.equals("A2")){ return new ReportServiceA2(); }else{ throw new IllegalArgumentException("不支持的类型"); } } public static void main(String[] args) { ReportService a1 = createService("A1"); String result = a1.getResult(); System.out.println(result); } }
输出:
我是A1
其实在SpringBoot中,也支持以依赖注入的方式实现工厂方法。
我们只需要对类稍加改造即可。
//接口实现不变 public interface ReportService { String getResult(); } //给实现类加上名字 @Component("A1") public class ReportServiceA1 implements ReportService { @Override public String getResult() { return "我是A1"; } } //给实现类加上名字 @Component("A2") public class ReportServiceA2 implements ReportService { @Override public String getResult() { return "我是A2"; } }
新工厂类实现
@Service public class ReportFactory { //这个地方是关键,项目启动时springboot会被所有ReportService实现类注入到这个map中 @Autowired private final Map<String,ReportService> map=new ConcurrentHashMap<>(); public ReportService get(String name){ return map.get(name); } }
测试一下,可以看出对应每个不同的实现类都只有唯一的一个实例,并且建立了name和实例的映射关系。
而且这种工厂方法的实现比自己手写if/else工厂方法优雅多了。
@SpringBootTest(classes= Application.class) class ReportFactoryTest { @Autowired private ReportFactory reportFactory; @Test void get() { ReportService a1 = reportFactory.get("A1"); ReportService a11 = reportFactory.get("A1"); System.out.println(a1); System.out.println(a11); System.out.println( a1.getResult()); ReportService a2 = reportFactory.get("A2"); System.out.println(a2.getResult()); } }
输出:
cn.jinka.gcdp.metacenter.application.metadata.ReportServiceA1@d3e9629
cn.jinka.gcdp.metacenter.application.metadata.ReportServiceA1@d3e9629
我是A1
我是A2