工厂模式
简单工厂
使用场景
工厂类负责创建的对象较少
客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不关心。
缺点
工厂类的职责过重,增加新的产品时需要修改工厂类的判断逻辑, 违背开闭原则。
不易于扩展过于复杂的产品结构。
工厂要创建的对象
public interface ICourse {
void init();
String getName();
}
public class JavaCourse implements ICourse {
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "Java";
}
}
public class PythonCourse implements ICourse{
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "Python";
}
}
工厂类
/**
* 简单工厂, 不是23种设计模式之一
*/
@Slf4j
public class SimpleCourseFactory {
/**
* 根据名称判断要创建的对象(典型的简单工厂)
* @param name
* @return
*/
public static ICourse createCourse(String name) {
switch (name) {
case "python":
return new PythonCourse();
case "java":
return new JavaCourse();
default:
return null;
}
}
// 根据全限定类名创建(升级的简单工厂)
public static ICourse creatCourseByClassName(String className) {
if (StringUtils.isBlank(className)) {
throw new IllegalArgumentException("className name is required");
}
try {
Class<?> aClass = Class.forName(className);
if (!ICourse.class.isAssignableFrom(aClass)) {
throw new IllegalArgumentException("class type wrong, not assignable from com.dreams.pattern.factory.simple.ICourse");
}
ICourse o = (ICourse) aClass.newInstance();
o.init();
return o;
} catch (Exception e) {
log.error("create instance for {}", className);
log.error("create instance for {}", e);
throw new IllegalArgumentException("can not create instance for className : " + className, e);
}
}
//简化, clasz必须是ICourse的实现类
public static ICourse createCourseByClasz(Class<? extends ICourse> clasz) {
try {
ICourse iCourse = clasz.newInstance();
iCourse.init();
return iCourse;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
工厂方法模式
工厂方法模式是指定义一个创建对象的接口,但让实现类类决定实例化哪个类, 工厂方法让类的实例化推迟到子类中进行。
define an interface for creating an object, but let subclass decide witch class to instantiate.
The factory method lets a class defer instantiation it uses to subclasses.
适用场景
创建对象需要大量重复的代码
客户端不依赖产品类实例如何被创建、实现等细节
一个类通过其子类来指定创建哪个类。
产品
public interface ICourse {
void init();
String getName();
}
public class JavaCourse implements ICourse {
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "Java";
}
}
public class PythonCourse implements ICourse{
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "Python";
}
}
工厂
public interface ICourseFactory {
ICourse create();
}
public class JavaCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
JavaCourse javaCourse = new JavaCourse();
javaCourse.init();
//do something
return javaCourse;
}
}
public class PythonCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
PythonCourse course = new PythonCourse();
course.init();
//do something
return course;
}
}
扩展产品&工厂
符合开闭原则
public class PhpCourse implements ICourse {
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "PHP";
}
}
public class PhpCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
PhpCourse phpCourse = new PhpCourse();
phpCourse.init();
//do something
return phpCourse;
}
}
扩展产品&工厂
符合开闭原则
public class PhpCourse implements ICourse {
@Override
public void init() {
//do something
}
@Override
public String getName() {
return "PHP";
}
}
public class PhpCourseFactory implements ICourseFactory {
@Override
public ICourse create() {
PhpCourse phpCourse = new PhpCourse();
phpCourse.init();
//do something
return phpCourse;
}
}
抽象工厂
提供一个创建一系列对象或相互依赖对象的接口,而无需指定它们具体的类。
考虑一门课程内容, 它包含视频内容和笔记, 对于不同的课程需要创建不同的视频内容和笔记。
后续可能的扩展
- 增加新课程
- 课程需要增加新内容,例如考试内容
案例
Note
public interface INote {
String getName();
void createNote();
}
public class JavaNote implements INote{
@Override
public String getName() {
return "Java Note";
}
@Override
public void createNote() {
System.out.println("记录Java笔记");
}
}
public class PythonNote implements INote {
@Override
public String getName() {
return "Python Note";
}
@Override
public void createNote() {
System.out.println("记录Python笔记");
}
}
Video
public interface IVideo {
void createVideo();
String getName();
}
public class JavaVideo implements IVideo {
@Override
public void createVideo() {
System.out.println("录制Java视频");
}
@Override
public String getName() {
return "Java Video";
}
}
public class PythonVideo implements IVideo {
@Override
public void createVideo() {
System.out.println("录制Python视频");
}
@Override
public String getName() {
return "Python Video";
}
}
Factory
public interface CourseFactory {
INote createNote();
IVideo createVideo();
}
public class JavaCourseFactory implements CourseFactory {
@Override
public INote createNote() {
JavaNote javaNote = new JavaNote();
javaNote.createNote();
return javaNote;
}
@Override
public IVideo createVideo() {
JavaVideo javaVideo = new JavaVideo();
javaVideo.createVideo();
return javaVideo;
}
}
public class PythonCourseFactory implements CourseFactory {
@Override
public INote createNote() {
PythonNote pythonNote = new PythonNote();
pythonNote.createNote();
return pythonNote;
}
@Override
public IVideo createVideo() {
PythonVideo pythonVideo = new PythonVideo();
pythonVideo.createVideo();
return pythonVideo;
}
}
Test
Java course
@Test
public void testJavaCourse() {
CourseFactory factory = new JavaCourseFactory(); //Java
IVideo video = factory.createVideo();
log.info("course.video : {}", video.getName());
INote note = factory.createNote();
log.info("course.note : {}", note.getName());
}
录制Java视频
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.video : Java Video
记录Java笔记
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.note : Java Note
Python course
@Test
public void testPythonCourse() {
CourseFactory factory = new PythonCourseFactory(); //Python
IVideo video = factory.createVideo();
log.info("course.video : {}", video.getName());
INote note = factory.createNote();
log.info("course.note : {}", note.getName());
}
录制Python视频
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.video : Python Video
记录Python笔记
[main] INFO com.dreams.pattern.factory.abctract.CourseFactoryTest - course.note : Python Note
参与者
- 抽象工厂
- 具体工厂
- 抽象产品
- 具体产品
- 客户端
优缺点
- 分类了具体的类
- 易于更换产品系列
- 有利于产品的一致性, 将一系列产品统一到一起创建。
- 难以支持新种类产品(新增具体产品)
- 新增产品需要新增抽象产品, 新增具体产品, 抽象工厂新增创建产品的接口, 所有已实现的具体工厂添加新产品的创建。
适用场景
客户端不依赖于产品类实例如何被创建、实现等细节。
强调一系列相关的产品对象一起使用,创建对象需要大量重复代码。
提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体的实现。
最佳实践
- 将具体工厂作为单例
- 创建产品, 抽象工厂只负责声明创建产品的接口, 真正产品的创建在具体工厂中实现
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义