定义:
简单工厂模式又叫作静态工厂方法模式,简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式,
应用场景:
对于产品种类相对较少的情况下,考虑使用简单工厂模式可以方便的创建所需的产品。使用简单工厂模式的用户只需要传入工厂类的参数,不需要关心如何创建对象的逻辑。
简单工厂模式的UML类图:
右上图可见,简单工厂模式包括三个部分:
-
简单工厂:是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
-
抽象产品,是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
-
具体产品:简单工厂模式的创建目标
通用写法:
public class Client{
public static void main(String[] args){
new SimpleFactory().makeProduct(1);
}
}
//抽象产品
public interface IProduct{
void doSomething();
}
//具体产品:ProductA
public class ProductA implements IProduct{
public void doSomething(){
System.out.println("i am Product A");
}
}
//具体产品:ProductB
public class ProductB implements IProduct{
public void doSomething(){
System.out.println("i am Product B");
}
}
//具体产品:ProductC
public class ProductC implements IProduct{
public void doSomething(){
System.out.println("i am Product C");
}
}
final class Const{
static final int PRODUCT_A =0;
static final int PRODUCT_B =1;
static final int PRODUCT_C =2;
}
public class SimpleFactory{
public static IProduct makeProduct(int kind){
switch(kind){
case Const.PRODUCT_A:
return new ProductA();
case Const.PRODUCT_B:
return new ProductB();
case Const.PRODUCT_C:
return new ProductC();
}
return null;
}
}
实例:
以课程为例,目前有java架构,大数据,人工智能等课程,已经形成了一个生态,我们可以定义一个课程标准ICourse接口
public interface ICourse{
public void record();
}
创建一个Java课程的实现类JavaCourse
public class JavaCourse implements ICourse{
public void record(){
System.out.println("录制java课程");
}
}
客户端调用代码如下:
public static void main(String[] args){
ICourse course = new JavaCourse();
course.record();
}
有上面代码可知,父类ICourse指向子类JavaCourse的引用,应用层代码需要依赖JavaCourse,如果业务扩展,则继续增加PythonCourse,甚至更多,那么客户端的依赖就会变的越来越臃肿。因此,用简单工厂模式对代码进行优化。
public class PythonCourse implements ICourse{
public void record(){
System.out.println("录制PythonCourse课程");
}
}
然后创建CourseFactory工厂类
public class CourseFactory{
public ICourse create(String name){
if("java".equals(name)){
return new JavaCourse();
}else if("python".equals(name)){
return new PythonCourse();
}else{
return null;
}
}
}
最后修改客户端调用代码
public class SimpleFactoryTest{
public static void main(String[] args){
CourseFactory factory = new CourseFactory();
factory.create("java");
}
}
客户端调用虽然简单了,但是如果业务继续扩展,要增加前段课程,则工厂中的create()方法就要随着产品链的丰富,每次都要修改代码逻辑,这不符合开闭原则。因此可以使用反射技术继续对代码进行优化。代码如下:
public class CourseFactory{
public ICourse create(String className){
try{
if(!(null == className || "".equals(className))){
return (ICourse)Class.forName(className).newInstance();
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
客户端调用代码如下:
public static void main(String[] args){
CourseFactory factory = new CourseFactory();
ICourse course = factory.create("com.XXX.JavaCourse");
course.record();
}
优化之后,产品不断丰富,不需要修改CourseFactory中的代码。但问题是,方法参数是字符串,可控性有待提高,而且需要强制转型,继续修改代码
public ICourse create(Class<? extends ICourse> clazz){
try{
if(null != clazz){
return clazz.newInstance();
}
}catch(Exception e){
e.printStackTrace();
}
}
优化客户端代码:
public static void main(String[] args){
CourseFactory factory = new CourseFactory();
ICourse course = factory.create(JavaCourse.class);
course.record();
}
简单工厂模式优点:
简单工厂模式的结构简单,调用方便,对于外界给定的信息,可以很方便的创建出相应的产品,工厂和产品的职责区分明确
简单工厂模式缺点:
简单工厂模式的工厂类单一,负责多有产品的创建,但当产品基数增加时,工厂类代码类就会非常臃肿,违背高聚合原则