一、工厂模式的作用,为什么要用工厂模式?
a.工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用Class B,那么只是调用B的方法,而至于B的实例化,就交给工厂类。
b.工厂模式可以降低代码重复。如果创建B过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。可以把这些创建对象B的代码放到工厂里统一管理。既减少了重复代码,也方便以后对B的维护。
c.工厂模式可以减少错误,因为工厂管理了对象的创建逻辑,使用者不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误。
二、工厂模式的一些适用场景。
对象的创建过程/实例化准备工作很复杂,需要很多初始化参数,查询数据库等。
类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
三、简单工厂模式。
创建一个工厂类,在类中通过传入的参数不同创建不同的实体类。有新需求时需要更改工厂类中的代码,违背了开闭原则。
//创建抽象产品类 ,定义具体产品的公共接口; interface ICourse { /** * 录制视频 * @return */ void record(); } //创建具体产品类(继承抽象产品类), 定义生产的具体产品; class JavaCourse implements ICourse { public void record() { System.out.println("录制Java课程"); } } class PythonCourse implements ICourse { public void record() { System.out.println("录制Python课程"); } }
//第一种方式,根据参数来判断哪个类来处理。 //新建工厂。 class CourseFactory { ICourse create(String name){ if("java".equals(name)){ return new JavaCourse(); }else if("python".equals(name)){ return new PythonCourse(); }else { return null; } } } //调用工厂类来实例化需要的类。 class testFactory(){ public static void main(String[] args) { CourseFactory factory = new CourseFactory(); ICourse course = factory.create("Java"); course.record(); } }
//第二种写法,通过反射的方式 public ICourse create(String className){ try { if (!(null == className || "".equals(className))) { return (ICourse) Class.forName(className).newInstance(); } }catch (Exception e){ e.printStackTrace(); } return null; } //调用(通过全路径去反射获取) ICourseFactory factory = new ICourseFactory(); ICourse course = factory.create("com.gupaoedu.vip.pattern.factory.JavaCourse"); course.record(); 或者 public ICourse create(Class<? extends ICourse> clazz) { try { if (null != clazz) { return clazz.newInstance(); } } catch (Exception e) { e.printStackTrace(); } return null; } //调用 CourseFactory factory = new CourseFactory(); ICourse course = factory.create(JavaCourse.class); course.record();
简单工厂模式的优点:
1、工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;
2、简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
3、客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
4、通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
简单工厂模式的缺点:
1、由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
2、使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4、简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
简单工厂模式的在JDK或者Spring当中的运用例子:
待补充
四、工厂方法模式
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
主要是将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
//步骤1: 创建抽象工厂类,定义具体工厂的公共接口 public interface ICourseFactory { ICourse create(); } //步骤2: 创建抽象产品类 ,定义具体产品的公共接口; public interface ICourse { void record(); } //步骤3: 创建具体产品类(继承抽象产品类), 定义生产的具体产品; //产品1 public class JavaCourse implements ICourse { public void record() { System.out.println("录制Java课程"); } } //产品2 public class PythonCourse implements ICourse { public void record() { System.out.println("录制Python课程"); } } //步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法(每个产品对应一个实现的工厂); //工厂1 public class JavaCourseFactory implements ICourseFactory { public ICourse create() { return new JavaCourse(); } } //工厂2 public class PythonCourseFactory implements ICourseFactory { public ICourse create() { return new PythonCourse(); } } //步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例 public class FactoryMethodTest { public static void main(String[] args) { ICourseFactory factory = new PythonCourseFactory(); ICourse course = factory.create(); course.record(); factory = new JavaCourseFactory(); course = factory.create(); course.record(); } }
工厂方法模式的优点:
1、更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
2、符合单一职责原则
每个具体工厂类只负责创建对应的产品
3、不使用静态工厂方法,可以形成基于继承的等级结构。
工厂方法模式的缺点:
1、添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
2、由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
3、虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
4、一个具体工厂只能创建一种具体产品
工厂方法模式的在JDK或者Spring当中的运用例子:
待补充
五、抽象工厂模式
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
代码和工厂方法模式类似,只是抽象工厂不但可以创建单个产品,而且还能创建产品族(关联产品)
//步骤1: 创建抽象工厂类,定义具体工厂的公共接口 public interface ICourseFactory { INote createNote(); IVideo createVideo(); } //步骤2: 创建抽象产品类 ,定义具体产品的公共接口(多个相关产品,形成产品族); //笔记 public interface INote { void edit(); } //视频 public interface IVideo { void record(); } //步骤3: 创建具体产品类(继承抽象产品类), 定义生产的具体产品; //产品1 public class JavaNote implements INote { public void edit() { System.out.println("编写Java笔记"); } } //产品2 public class JavaVideo implements IVideo { public void record() { System.out.println("录制Java视频"); } } //步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法(每个产品对应一个实现的工厂); //只需要一个工厂,就能处理上面多种关联产品,如果产品之前存在关联关系,那么可以直 //接在此工厂内部进行维护 public class JavaCourseFactory implements CourseFactory { public INote createNote() { return new JavaNote(); } public IVideo createVideo() { return new JavaVideo(); } } //步骤5:外界通过调用具体工厂类的方法,创建多个产品。 public class FactoryMethodTest { public static void main(String[] args) { JavaCourseFactory factory = new JavaCourseFactory(); factory.createNote().edit(); factory.createVideo().record(); } }
抽象工厂模式的优点:
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
抽象工厂模式的缺点:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
抽象工厂在JDK和Spring中的运用:
待补充