简单工厂模式
Simple Factory Pattern,是指一个工厂对象决定创建出哪一种产品类的实例,属于创建型模式。
适用场景
1、工厂类负责创建的对象较少。
2、客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。
优点
只需要传入一个正确的参数,就可以获取你所需要的对象,无需知道其创建细节。
缺点
1、工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑违背开闭原则。
2、不易于扩展过于复杂的产品结构。
反例
每一个课程都要自己new,会产生很多冗余代码,没有面向抽象编程。
类图
package pattern.factory.simplefactory;
public class Test {
public static void main(String[] args) {
Couse couse = new Couse();
couse.record();;
JavaCouse javaCouse = new JavaCouse();
javaCouse.record();
}
}
package pattern.factory.simplefactory;
/**
* 课程
*/
public class Couse {
public void record() {
System.out.println("录制Python课程");
}
}
package pattern.factory.simplefactory;
/**
* 录制Java课程
*/
public class JavaCouse {
public void record() {
System.out.println("录制Java课程");
}
}
正例
反例有一个共性,都叫课程couse。
先从总体出发,先不考虑细节,先把课程抽象出来一个接口。
架构师思维,预先考虑好未来可能会发生的改变。
工厂:把创建对象的过程包装起来,具体的创建用户不用关心,用户只需要关心需要创建什么。
package pattern.factory.simplefactory;
public class Test {
public static void main(String[] args) {
new CouseFactory().create("Java").record();
}
}
package pattern.factory.simplefactory;
/**
* 课程
*/
public interface ICouse {
void record();
}
package pattern.factory.simplefactory;
/**
* 录制Java课程
*/
public class JavaCouse implements ICouse{
@Override
public void record() {
System.out.println("录制Java课程");
}
}
package pattern.factory.simplefactory;
/**
* 录制Python课程
*/
public class PythonCouse implements ICouse {
@Override
public void record() {
System.out.println("Python课程");
}
}
package pattern.factory.simplefactory;
/**
* 课程工厂
*/
public class CouseFactory {
public ICouse create(String name) {
if("java".equals(name)) {
return new JavaCouse();
}else if("python".equals(name)){
return new PythonCouse();
}
return null;
}
}
优点:
经过上面的改造,用户只跟工厂打交道,只在CouseFactory.create(String name)方法中传入一个字符串,就可以得到自己想要的对象。这是工厂模式的思想。
缺点:
1、CouseFactory.create(String name) 方法体根据传入的name进行if else判断每次增加课程Couse都需更改此工厂方法,以适配新的课程Couse,容易出错。不符合开闭原则。
2、CouseFactory.create(String name) 入参字符串用户容易传错,没有章法,显然这不是很好的方式。
运用Java反射技术升级1
改造CouseFactory工厂类,传入全类名pattern.factory.simplefactory.JavaCouse
package pattern.factory.simplefactory;
public class Test {
public static void main(String[] args) {
new CouseFactory().create("pattern.factory.simplefactory.JavaCouse").record();
}
}
package pattern.factory.simplefactory;
/**
* 课程工厂
*/
public class CouseFactory {
public ICouse create(String className) {
try {
if(null != className || "".equals(className)) {
return (ICouse) Class.forName(className).newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
优点:
1、经过上面的改造,用户只跟工厂打交道,只在CouseFactory.create(String className)方法中传入一个字符串,就可以得到自己想要的对象。这是工厂模式的思想。
2、CouseFactory.create(String className) 每次增加课程Couse都不需更改此工厂方法,用户只需要输入正确的全类名,就可以适配新的课程Couse。对于此产品而言符合开闭原则。
缺点:
1、CouseFactory.create(String className) 入参全类名用户容易传错,显然这不是很好的方式。
运用Java反射技术升级2
package pattern.factory.simplefactory;
public class Test {
public static void main(String[] args) {
new CouseFactory().create(JavaCouse.class).record();
}
}
package pattern.factory.simplefactory;
/**
* 课程工厂
*/
public class CouseFactory {
public ICouse create(Class clazz) {
try {
if(clazz != null) {
return (ICouse) clazz.newInstance();
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
优点:
1、经过上面的改造,用户只跟工厂打交道,只在CouseFactory.create(String className)方法中传入一个字符串,就可以得到自己想要的对象。这是工厂模式的思想。
2、CouseFactory.create(String className) 每次增加课程Couse都不需更改此工厂方法,用户只需要输入正确的全类名,就可以适配新的课程Couse。对于此产品而言符合开闭原则。
3、CouseFactory.create(String className) 入参是Class用户不会传错。
缺点:
1、CouseFactory.create(Class clazz) 入参是Class用户不会传错了,但是可能会出现另外一个问题return (ICouse) clazz.newInstance();如果对类没有约束,这里强转成ICouse就会发生异常。
运用Java反射技术升级3
package pattern.factory.simplefactory;
/**
* 课程工厂
*/
public class CouseFactory {
public ICouse create(Class<? extends ICouse> clazz) {
try {
if(clazz != null) {
return clazz.newInstance();
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
优点:
用户只需要跟工厂打交道,CouseFactory.create(Class<? extends ICouse> clazz)方法中,用户只需且只能传入产品ICouse的子类符合单一职责原则,增加新的课程Couse不需要改变工厂方法,对于此产品而言符合开闭原则。
其他例子
1、Jdk中例子:
Calendar.getInstance();
2、Log4j中的例子:
LoggerFactory.getLogger();