简述
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
demo
场景:根据参数的不同去生产不同类型的视频,如录制Java,python等视频
1.创建抽象类,赋予生产视频的功能
public abstract class Video {
public abstract void produce();
}
2.创建具体的实现类去生产视频
public class JavaVideo extends Video{
@Override
public void produce() {
System.out.println("生产Java视频...");
}
}
public class PythonVideo extends Video{
@Override
public void produce() {
System.out.println("生产python视频....");
}
}
3.创建工厂类去生产对象
public class VideoFactory {
/**
* 根据类型创建具体的某个对象,但每次新增一个类型就需要更新工厂类,违反了开闭原则
* @param type
* @return
*/
public Video createVideo(String type) {
if ("python".equalsIgnoreCase(type)) {
return new PythonVideo();
} else if ("Java".equalsIgnoreCase(type)) {
return new JavaVideo();
}
return null;
}
/**
* 利用反射对创建对象做了优化,对修改关闭
* @param clazz
* @return
*/
public Video createVideo(Class clazz) {
Video video;
try {
video = (Video) Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return video;
}
}
4.客户端调用
public class Test {
public static void main(String[] args) {
// 1.
VideoFactory factory1 = new VideoFactory();
Video video1 = factory1.createVideo("Java");
if (video1 == null) {
return;
}
video1.produce();
// 2.
VideoFactory factory2 = new VideoFactory();
Video video2 = factory2.createVideo(PythonVideo.class);
if (video2 == null) {
return;
}
video2.produce();
}
}
以前我们写代码客户端都是通过new PythonVideo或者new JavaVideo 去创建具体的某个实际对象,简单工厂模式则是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。这样做的好处在于客户端不必在乎对象是如何产生的,只需要传入指定的条件就返回一个需要的对象。且这样能够剔除PythonVideo或者JavaVideo这种具体实现类的依赖
优缺点
优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。违反开闭原则
使用场景
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
源码体现
JDK中Calendar类的getInstance方法: