(零)简单工厂模式
工厂模式的使用原则就是将构造复杂对象的工作交给指定的人去做。调用者不需要关心具体如何实现,只需要传入自己想要的工厂类参数即可。简单工厂模式专门定义一个工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式,也叫静态工厂模式,它并不在我们常说的23种设计模式之中。
1,简单工厂模式的设计原则:
- 简单工厂(SimpleFactory):负责实现所有实例的内部逻辑,由他指定该实例哪种产品。
- 抽象产品(IProduct):所有产品实例的顶级接口。
- 具体产品(ConcreteProduct):简单工厂创建的具体产品 。
![image-20210201091428579](https://cdn.jsdelivr.net/gh/hellolsk/imageSource//imageblog/20210201091430.png)
下面我们以一个具体案例分析简单工厂模式的使用:
2,简单案例
同样是录制课程,现在有java,python课程等,当我们需要新增课程时如何利用简单工厂模式进行设计呢?第一步,设计CourseFactory负责创建课程的逻辑,可以想到它是个if-else或者是switch-case的模式;传入什么参数,工厂就实例化出什么类型的课程;第二部,创建父类接口ICourse,这里它只有一个方法record记录课程;第三步,动态的增加的陆续上线的课程。
public class CourseFactory {
public static ICourse create(String name) {
if("java".equals(name)){
return new JavaCourse();
}else if("python".equals(name)){
return new PythonCourse();
}else {
return null;
}
}
}
public interface ICourse {
void record();
}
public class JavaCourse implements ICourse {
@Override
public void record() {
System.out.println("录制java课程");
}
}
public class PythonCourse implements ICourse {
@Override
public void record() {
System.out.println("录制python课程");
}
}
public class Test {
public static void main(String[] args) {
ICourse iCourse = CourseFactory.create("java");
iCourse.record();
}
}
2.1,第一轮优化:
当我们上线新的课程时,除了增加新的课程为,还需要修改工厂中的create方法,违背了开闭原则OCP,我们采用反射机制,根据全类名动态的决定实例的对象。
public class CourseFactory {
public static ICourse create(String className) {
// 2,采用反射,解决添加其他课程,需要更改工厂类的create方法的问题
if (className != null && !"".equals(className)) {
try {
return (ICourse) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
public class Test {
public static void main(String[] args) {
ICourse iCourse = CourseFactory.create(
"com.lsk.creationalPatterns.simpleFactoryPattern.JavaCourse");
iCourse.record();
}
}
2.2,第二轮优化:
上一轮优化中,传入字符参数的有些臃肿而且还需要做强制类型转换,这里我们直接将参数改为类名的形式。
public class CourseFactory {
// 3,解决字符串参数的弊端以及强制转换的问题
public static ICourse create(Class<? extends ICourse> clazz){
if(clazz !=null){
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return null;
}
}
public class Test {
public static void main(String[] args) {
ICourse iCourse = CourseFactory.create(JavaCourse.class);
iCourse.record();
}
}
![image-20210131214500850](https://cdn.jsdelivr.net/gh/hellolsk/imageSource//imageblog/20210131214502.png)
3,简单工厂模式点评
3.1,工厂模式要点
为什么需要采用工厂模式?直接new一个不可以?
工厂模式就是将对象的创建和对象本身业务处理分开,降低耦合;
工厂模式负责产品创建的逻辑,决定对象何时进行实例,而应用层客户端只需就可以免除创建产品的责任,直接消费产品,职责分明;
客户端不需要知道产品的具体类名,仅需要知道产品对应的参数即可,减少调用的记忆复杂度;
3.2,不足分析
1,扩展困难,添加新产品需要修改创建逻辑;
2,工厂类职责过重,一旦出现问题,整个系统都不能工作;
3,简单工厂使用了静态方法,造成工厂角色无法形成基于继承的等级结构。
3.3,适用场景
1,产品对象较少,不需要工厂维护复杂的创建逻辑;
2,客户端不关心创建细节,只需知道产品对应参数。
简单工厂模式结构简单,调用方便,非常适合需要动态增加产品的情形。作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。且当产品基数增加时,工厂类就会非常臃肿。