简单工厂模式
由一个工厂对象决定创建哪一中产品类的实例,适合工厂类创建的对象比较少的场景,客户端只需要传入工厂类的参数,对于如何创建对象并不关心。
下面以课程为例
首先创建一个课程标准接口ICourse
public interface ICourse {
/**
* 录制视频
*/
public void record();
}
创建一个java课程实现类javaCourse
public class JavaCourse implements ICourse{
@Override
public void record() {
System.out.println("录制java视频课程");
}
}
此时,如果想扩展其他课程只需要实现Icourse类即可
public class PythonCourse implements ICourse{
@Override
public void record() {
System.out.println("录制python视频课程");
}
}
创建工厂类
public class CourseFactory {
public static ICourse create(Class<? extends ICourse> clazz) {
if (null != clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return null;
}
}
简单工厂测试
@Test
public void testSimpleFactory() {
ICourse javaCourse = CourseFactory.create(JavaCourse.class);
javaCourse.record();
}
简单工厂模式存在的问题
随着产品的丰富,工厂的职责会变得越来越多,变得难以维护
工厂方法模式
指定一个创建对象的接口,让实现这个接口的类来决定实例化那个类(对工厂也进行抽象),工厂方法模式让类的实例化推迟到子类进行。
创建工厂抽象类
public interface ICourseFactory {
ICourse create();
}
创建JavaCourse类
public class JavaCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new JavaCourse();
}
}
创建PythonCourse类
public class PythonCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new PythonCourse();
}
}
工厂方法模式测试类
@Test
public void testMethodFactory() {
ICourseFactory javaCourseFactory = new JavaCourseFactory();
ICourse javaCourse = javaCourseFactory.create();
javaCourse.record();
}
工厂方法模式适用场景
- 创建对象需要大量重复代码
- 客户端不依赖于产品类如何被创建、被实现的细节
- 一个类通过其子类来指定创建那个对象
缺点
- 类的数量容易过多
- 增加了系统的抽象性和理解难度
抽象工厂模式
指提供一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的实现类。
回到上面的例子,如果现在需要扩充课堂笔记功能
创建笔记类标准接口
public interface INote {
void edit();
}
创建视频类标准接口
public interface IVideo {
void record();
}
创建课程工厂抽象接口
public interface CourseFactory {
INote createNote();
IVideo createVideo();
}
创建Java课程产品簇
public class JavaNote implements INote{
@Override
public void edit() {
System.out.println("编写java笔记");
}
}
public class JavaVideo implements IVideo{
@Override
public void record() {
System.out.println("录制java视频");
}
}
public class JavaCourseFactory implements CourseFactory {
@Override
public INote createNote() {
return new JavaNote();
}
@Override
public IVideo createVideo() {
return new JavaVideo();
}
}
创建Python类产品簇
public class PythonCourseFactory implements CourseFactory {
@Override
public INote createNote() {
return new PythonNote();
}
@Override
public IVideo createVideo() {
return new PythonVideo();
}
}
public class PythonNote implements INote{
@Override
public void edit() {
System.out.println("编写python笔记");
}
}
public class PythonVideo implements IVideo{
@Override
public void record() {
System.out.println("录制python视频");
}
}
上面的代码一共有Java课程和Python课程两个产品簇,有视频课和课堂笔记两个产品,如果现在想要扩充一个课程源码这个产品,我们的代码从抽象工厂到具体工厂都需要改动。如果产品变动不会很频繁的话,问题不大。