普通创建对象的方式,如:
interface ICourse{
public void record();
}
class JavaCourse implements ICourse{
@Override
public void record() {
System.out.println("Java 课程");
}
}
public class Test {
public static void main(String[] args) {
ICourse course = new JavaCourse();
course.record();
}
}
以上代码,父类ICourse指向子类JavaCourse的引用,应用层代码需要依赖JavaCourse,如果业务扩展,继续增加PythonCourse甚至更多,那么我们的客户端的依赖会变得越来越臃肿。因此,我们要想办法把这种依赖减弱,把创建细节隐藏。
简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例,不属于GOF 23种设计模式。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心。
interface ICourse{
public void record();
}
class JavaCourse implements ICourse{
@Override
public void record() {
System.out.println("Java 课程");
}
}
class PythonCourse implements ICourse{
@Override
public void record() {
System.out.println("Python 课程");
}
}
/**
* 简单工厂类
*/
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 Test {
public static void main(String[] args) {
CourseFactory courseFactory = new CourseFactory();
courseFactory.create("Java");
}
}
为了更方便调用,也可以把create改为静态方法。
如果业务继续扩展,那么工厂中的create()就需要修改代码逻辑,不符合开闭原则。因此可以采用反射技术进行优化:
/**
* 简单工厂类
*/
class CourseFactory{
public ICourse create(String className) {
if((null == className || "".equals(className))){
try {
return (ICourse) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory = new CourseFactory();
courseFactory.create("com.factory.simplefactory.JavaCourse");
}
}
方法参数是字符串,可控性有待提升,而且还需要强制转型。
/**
* 简单工厂类
*/
class CourseFactory{
public ICourse create(Class<? extends ICourse> clazz) {
if(null != clazz){
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory = new CourseFactory();
courseFactory.create(JavaCourse.class);
}
}
工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
/**
* 工厂模式
*/
interface ICourseFactory{
ICourse create();
}
class JavaCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new JavaCourse();
}
}
class PythonCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new PythonCourse();
}
}
public class Test {
public static void main(String[] args) {
ICourseFactory iCourseFactory = new JavaCourseFactory();
ICourse iCourse = iCourseFactory.create();
}
}
工厂方法适用以下场景:
- 创建对象需要大量重复的代码
- 客户端不依赖于产品类实例如何被创建、实现等细节
- 一个类通过其子类来指定创建哪个对象
工厂方法的缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的复杂性
抽象工厂模式(Abstract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。强调的是一系列相关的产品对象一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖具体实现。
interface INote{
void edit();
}
class JavaNote implements INote{
@Override
public void edit() {
System.out.println("编写Java 笔记");
}
}
/**
* 抽象工厂类
*/
abstract class AbstractCourseFactory{
public void init(){
System.out.println("初始化基础数据");
}
protected abstract ICourse createCourse();
protected abstract INote createNote();
}
class JavaAbstractCourseFactory extends AbstractCourseFactory{
@Override
protected ICourse createCourse() {
super.init();
return new JavaCourse();
}
@Override
protected INote createNote() {
super.init();
return new JavaNote();
}
}
public class Test {
public static void main(String[] args) {
AbstractCourseFactory abstractCourseFactory = new JavaAbstractCourseFactory();
abstractCourseFactory.createCourse().record();
abstractCourseFactory.createNote().edit();
}
}
上述代码完整的描述了创建一个产品族的过程。但是如何如果将Video类加入其中,所有代码都需要调整,不符合开闭原则。抽象工厂方法的缺点是:
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
- 增加了系统的复杂性。