工厂模式是最基本的也是最重要的模式,因为它方便我们能写出高质量、高效率的代码。只有掌握了工厂模式,我们才不会重复造轮子。今天将从最简单的工厂模式开始一步步深入讲解,告诉大家自己写是怎么用的,框架又是如何实现,我们能从框架实现获得怎么样的灵感。
首先看看工厂模式的类图:
工厂模式由一个接口类加一个对应的工厂类实现的,接口类提供所有要创建出来的实体所需要的方法,工厂类只负责一件事:创建实现类的对象的方法。
先提供出接口类和实现类:
public interface ICar {
void getBrand();
}
public class Audi implements ICar {
public void getBrand() {
System.out.printf("My brand is %s \n", Audi.class.getSimpleName());
}
}
public class Benz implements ICar {
public void getBrand() {
System.out.printf("My brand is %s \n", Benz.class.getSimpleName());
}
}
实现类会把类名打出来,我们现在要写个工厂类负责构造实现类的对象。
public class SimpleFactory1 {
public ICar createCar(String carName){
if("audi".equals(carName)){
return new Audi();
} else if ("benz".equals(carName)) {
return new Benz();
}
return null;
}
public static void main(String[] args) {
SimpleFactory1 carFactory = new SimpleFactory1();
ICar audi = carFactory.createCar("audi");
audi.getBrand();
ICar benz = carFactory.createCar("benz");
benz.getBrand();
}
}
工厂类采用的是根据传入类型判断创建哪个实体类,这种方式是实现起来很简单,有几种类型就相应的写多个if...else...分支即可。但这种工厂模式让人感觉很低能,因为每次需要增加一种类型的车辆,不仅要加相应的实体类,还要修改工厂类,明显违背了开闭原则。现在提供第二种工厂类:
public class SimpleFactory2 {
public ICar createCar(Class<? extends ICar> carClass){
try {
return carClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
SimpleFactory2 carFactory = new SimpleFactory2();
ICar audi = carFactory.createCar(Audi.class);
audi.getBrand();
ICar benz = carFactory.createCar(Benz.class);
benz.getBrand();
}
第二种工厂类的实现是根据实体类的Class的类型来自动生成实例,这种方式极大了提升了程序的扩展性,后续工厂类不需要做任何更改,只要加让实体类实现ICar接口,那么就能通过工厂类生产出相应的车辆。
现在最热门的Spring框架的IOC就是基于工厂模式,IOC通过DI(依赖注入)的方式将bean的创建交给了Spring Container,Spring Container 自动帮我们创建对象,我们只需要使用即可。
下面将采用Spring提供的一些组件来实现一个简单工厂,首先原有的实体类需要做下改造,类上加了@Component注解:
@Component
public class Audi implements ICar {
public void getBrand() {
System.out.printf("My brand is %s \n", Audi.class.getSimpleName());
}
}
public class SpringFactory {
public ICar createCar(String carName){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.discover.amazing.model");
return (ICar) context.getBean(carName);
}
public static void main(String[] args) {
SpringFactory springFactory = new SpringFactory();
ICar carBean = springFactory.createCar("audi");
carBean.getBrand();
}
}
Spring 这个工厂和前面的两种实现方式有没有本质区别呢,必须有,毕竟Spring 这么强大的世界级框架能被成千上万的企业使用有其道理。前面已经提示了,Spring 框架有Spring 容器,Spring 容器在启动的时候已经创建了,所有被@Component注解标注的实体类都会被扫描到放入容器中,下次使用是直接从容器中取出对象,不会再new新的对象。
可见,理解设计模式非常重要,通过设计模式,我们才能更深入的理解各种框架,理解了框架本质和思想,才能利用框架写出高质量的代码。