工厂模式
1、简单工厂模式
简单工厂模式适用于工厂类负责创建的对象较少的情况,客户端只需要传入工厂类的参数,具体的创建细节客户端不需要关心,由工厂类具体实现。
由一个工厂对象决定创建出哪一种产品类的实例,属于创建型模式。
减少代码的冗余程度
看代码
- 定义顶层工厂接口,提供一个所有产品都要实现的方法
public interface ICourse {
void record();
}
- 定义两种课程,java或者python
public class JavaCourse implements ICourse {
public void record() {
System.out.println("录制Java课程");
}
}
public class PythonCourse implements ICourse {
public void record() {
System.out.println("录制Python课程");
}
}
- 创建一个工厂类根据参数创建对应的对象
public class CourseFactory {
public ICourse create(Class<? extends ICourse> clazz){
try {
if (null != clazz) {
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
- 测试类
public class SimpleFactoryTest {
public static void main(String[] args) {
CourseFactory factory = new CourseFactory();
ICourse course = factory.create(JavaCourse.class);
course.record();
}
}
如果没有工厂的时候,我们需要每次根据需要去new我们对应的产品,但是当如果每个产品创建的过程非常复杂的时候,每次去new都会产生大量的冗余代码。
有了工厂我们只需要传入对应的想要的产品,由工厂去给我们创建一个我们需要的产品,具体的创建细节全部由工厂实现。
简单工厂解决的问题主要就是隐藏复杂的创建逻辑,方便客户端使用。
Calendar就是一个简单工厂的实现
LoggerFactory也是一个简单工厂的实现
简单工厂优点:
只需要一个参数就可以获取到对应产品。
简单工厂的问题:
工厂职责过重,增加新产品都要修改工厂类创建逻辑,违背开闭原则。
2、工厂方法模式
工厂方法模式是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法模式让类的实例化推迟到子类中进行。
解决的问题就是产品链越来越丰富,创建变得越来越复杂的情况。
- 定义一个超级工厂,接口,所有子工厂来实现这个规范接口
public interface ICourseFactory {
ICourse create();
}
- 定义两个子工厂,实现超级工厂这个接口规范
public class JavaCourseFactory implements ICourseFactory {
public ICourse create() {
return new JavaCourse();//这个类定义在上面简单工厂
}
}
public class PythonCourseFactory implements ICourseFactory {
public ICourse create() {
return new PythonCourse();//这个类定义在上面简单工厂
}
}
- 测试类
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();
}
}
可以看到,当产品链越来越丰富的时候,我们每次只需要新增一个新的工厂实现超级工厂这个接口规范即可,不用去改动源代码。
优点:
用户只需要关心产品对应的工厂,无须关心创建的细节。扩展容易
缺点:
产品越来越多会导致代码结构越来越复杂
3、抽象工厂
抽象工厂模式是指提供一个创建一系列相关或相互依赖的对象的接口,无须指定他们具体的类
课程有java、python,每种课程又有具体的产品 视频、笔记,这种通过简单工厂和工厂方法模式无法满足
- 顶层工厂(超级工厂)
//工厂既可以创建视频也可以创建笔记
public interface CourseFactory {
INote createNote();
IVideo createVideo();
}
- 两种产品规范
public interface INote {
void edit();
}
public interface IVideo {
void record();
}
- 创建java的产品和工厂
//Java视频产品
public class JavaVideo implements IVideo {
public void record() {
System.out.println("录制Java视频");
}
}
//Java笔记产品
public class JavaNote implements INote {
public void edit() {
System.out.println("编写Java笔记");
}
}
//Java工厂,产出视频和笔记
public class JavaCourseFactory implements CourseFactory {
public INote createNote() {
return new JavaNote();
}
public IVideo createVideo() {
return new JavaVideo();
}
}
- 同样创建python的产品和工厂
//python笔记产品
public class PythonNote implements INote {
public void edit() {
System.out.println("编写Python笔记");
}
}
//python视频产品
public class PythonVideo implements IVideo {
public void record() {
System.out.println("录制Python视频");
}
}
//python工厂产出两种产品
public class PythonCourseFactory implements CourseFactory {
public INote createNote() {
return new PythonNote();
}
public IVideo createVideo() {
return new PythonVideo();
}
}
- 测试类
public class AbstractFactoryTest {
public static void main(String[] args) {
JavaCourseFactory factory = new JavaCourseFactory();
factory.createNote().edit();
factory.createVideo().record();
}
}
抽象工厂其实是不符合开闭原则的,当我们每增加一个产品,需要在超级工厂中加一个抽象方法,所有的产品都需要改动实现这个方法。所以他有自己的使用场景,并不适用改动频繁的业务。
优点:
具体的产品在应用层代码隔离,无须关心创建细节
将一个系列的产品族统一到一起创建
缺点:
规定了所有可能被创建的产品的集合,产品族中扩展新产品困难,需要修改抽象工厂的接口
增加了系统的复杂度和理解难度