简单工厂其实并不能叫做设计模式,更多的像是一种编程习惯,只是将创建类的对象集中在一起创建,根据用户传入的类型判断创造什么实例返回。简单的说,有个类专门用来创造实例,像一个工厂,用户想要什么就去这个工厂提供的接口中去获取,工厂类收到请求后进行判断,看用户要的是什么类型,然后进行创建返回。
简单工厂实例
有个抽象类 Video
public abstract class Video {
/**
* 测试方法
*/
public abstract void produce();
}
有两个子类继承它
public class JavaVideo extends Video{
public void produce() {
System.out.println("这是一个 JavaVideo");
}
}
public class PythonVideo extends Video {
public void produce() {
System.out.println("这是一个 PythonVideo");
}
}
有个创建这些类的抽象工厂类
public class VideoFactory {
public static Video getVideo(String type) {
if ("java".equalsIgnoreCase(type)) {
return new JavaVideo();
} else if ("python".equalsIgnoreCase(type)) {
return new PythonVideo();
} else {
return null;
}
}
}
测试类如下
public class Test {
public static void main(String[] args) {
Video video = VideoFactory.getVideo("java");
video.produce();
video = VideoFactory.getVideo("python");
video.produce();
}
}
很简单的逻辑,可以看到简单工厂做的事真的很简单,就是根据出传入的字符串进行匹配返回对应的类实例。
简单工厂的缺点
可以得出,如果想要创建的类很多的话,那么就要写很多的 if(或者 switch…case),这样每次添加一个类都得修改工厂类,这就违背了开闭原则,即对修改关闭。所以说简单的工厂的职责很简单,只是进行简单的判断,适用于比较少的类的创建。
简单工厂的改进
虽然说简单工厂的职责很简单,但是我们可以让他稍微的"智能"一点,现在假设不是传入字符串类型,而是传入类类型,那么是否可以根据传入哪个类的类型就能获取哪个类呢?这是可以的,我们可以借助 java 的反射机制简单的实现这一功能,改进后的工厂类如下
public static Video getVideo(Class clazz) {
Video video = null;
try {
video = (Video)Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return video;
}
这样,客户端在调用的时候使用如下的方法
public class Test {
public static void main(String[] args) {
// Video video = VideoFactory.getVideo("java");
// video.produce();
Video video = VideoFactory.getVideo(JavaVideo.class);
video.produce();
}
}
总结
简单工厂基本上能够一眼看出来,要么使用反射直接获取,要么就是对传入的类型进行判断返回具体类型。更像是本来属于正常的判断程序代码,只不过由于多次使用到,为了降低代码的冗余,索性将这一块单独拿出来进行简单的封装形成了简单工厂模式,但并不是真正意义上的设计模式,只是一种编程习惯。
以上