当前位置: 首页 > news >正文

简单工厂模式 Simple Factory Pattern

基本内容

简单工厂模式指的是由一个工厂对象决定创建哪一种产品类的实例。
虽然简单工厂模式不属于GoF的23种之一,但是使用也很广泛。尤其适合工厂类创建的对象较少的场景。客户端只需要传入工厂类的参数,不需要知道创建对象过程。

优缺点

优点

解耦:

客户端与具体实现类解耦,客户端只需要知道抽象接口和工厂类,而不需要知道具体的产品类。

集中管理:

对象的创建逻辑集中在工厂类中,便于统一管理和修改。

易于扩展:

如果需要新增一种产品,只需要添加一个新的具体产品类,并在工厂类中添加相应的创建逻辑,而不需要修改客户端代码。

缺点

工厂类职责过重:

工厂类集中了所有产品的创建逻辑,一旦工厂类出现问题,可能会影响整个系统。此外如果产品类型非常多,工厂类的代码可能会变得臃肿,不易维护

实例

public interface ICourse {public void record();
}
public class CCourse implements ICourse{@Overridepublic void record() {System.out.println("正在记录C语言课程");}
}
public class JavaCourse implements ICourse{@Overridepublic void record() {System.out.println("正在录制Java课程");}
}
public class PythonCourse implements ICourse{@Overridepublic void record() {System.out.println("python课程正在录制中");}
}
public class CourseFactory {public ICourse create(String name){if("java".equals(name)){return new JavaCourse();}else if("python".equals(name)){return new PythonCourse();}else if("C".equals(name)) {return new CCourse();}else{System.out.println("没找到对应类,无法生成");return null;}}
}
public class Test {public static void main(String[] args) {CourseFactory courseFactory = new CourseFactory();ICourse python = courseFactory.create("python");python.record();}
}

在上面代码中,CourseFactory 是工厂类,负责创建 ICourse 的实现类。
客户端(Test 类)通过 CourseFactory.create(“python”) 获取 PythonCourse 实例,而不是直接 new PythonCourse()。工厂类根据 name 参数决定返回哪种课程实例。

解耦客户端与具体实现
客户端不需要知道 PythonCourse、JavaCourse 等具体类,只需要通过工厂类获取对象。
集中管理对象创建逻辑
如果新增课程(如 GoCourse),只需修改 CourseFactory,而不需要修改客户端代码。
提高代码可维护性
工厂类封装了对象创建逻辑,使代码更清晰、更易于扩展。

当然我们也可以将create方法改为静态类,方便调用。

简单工厂模式在jdk源码中也有所体现。可以看看Calendar.java里面的createCalendar方法:

private static Calendar createCalendar(TimeZone zone,Locale aLocale){CalendarProvider provider =LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();if (provider != null) {try {return provider.getInstance(zone, aLocale);} catch (IllegalArgumentException iae) {// fall back to the default instantiation}}Calendar cal = null;if (aLocale.hasExtensions()) {String caltype = aLocale.getUnicodeLocaleType("ca");if (caltype != null) {cal = switch (caltype) {case "buddhist" -> new BuddhistCalendar(zone, aLocale);case "japanese" -> new JapaneseImperialCalendar(zone, aLocale);case "gregory"  -> new GregorianCalendar(zone, aLocale);default         -> null;};}}if (cal == null) {// If no known calendar type is explicitly specified,// perform the traditional way to create a Calendar:// create a BuddhistCalendar for th_TH locale,// a JapaneseImperialCalendar for ja_JP_JP locale, or// a GregorianCalendar for any other locales.// NOTE: The language, country and variant strings are interned.if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {cal = new BuddhistCalendar(zone, aLocale);} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"&& aLocale.getCountry() == "JP") {cal = new JapaneseImperialCalendar(zone, aLocale);} else {cal = new GregorianCalendar(zone, aLocale);}}return cal;}

在这里插入图片描述
这部分是不是和CourseFactory里面的create方法很像

优化

我们可以利用反射机制,进一步优化。

public class CourseFactory {public ICourse create(String className){try{if(!(null==className||"".equals(className))){return (ICourse) Class.forName(className).newInstance();}} catch (Exception e) {e.printStackTrace();}return null;}}

传入class的全路径名

public class Test {public static void main(String[] args) {CourseFactory courseFactory = new CourseFactory();ICourse python = courseFactory.create("com.gupaoedu.vip.design.pattern.simplefactory.PythonCourse");python.record();}
}

如果我们考虑到输入参数是字符串,可控性较差,还需要强制类型转换,可以再改一下create方法:

public ICourse create(Class<? extends ICourse> clazz){try{if(null!=clazz){return clazz.newInstance();}} catch (Exception e) {e.printStackTrace();}return null;}
public class Test {public static void main(String[] args) {CourseFactory courseFactory = new CourseFactory();ICourse python = courseFactory.create(PythonCourse.class);python.record();}
}
http://www.dtcms.com/a/302859.html

相关文章:

  • Qt元类型系统(QMetaType)详解
  • 11、Docker Compose 配置Mysql主从(单虚拟机)
  • 树状数组的概念、结构及实现
  • 塔能科技物联运维平台及城市照明市场竞争力分析
  • 国产测试用例管理工具横向评测:DevOps时代如何选择最适合的协作平台?
  • window显示驱动开发—RecycleCreateCommandList
  • Angular 依赖注入
  • 网络 编程
  • 洛谷刷题7.28
  • 基于AFLFast的fuzz自动化漏洞挖掘(1)
  • 【HTTP】防XSS+SQL注入:自定义HttpMessageConverter过滤链深度解决方案
  • 【React Context API 优化与性能实践指南】
  • DBAPI 实现分页查询的两种方法
  • 阿里云Ubuntu 22.04 ssh隔一段时间自动断开的解决方法
  • 【力扣热题100】哈希——两数之和
  • 【mysql】—— mysql中的timestamp 和 datetime(6) 有什么区别,为什么有的地方不建议使用timestamp
  • 智能制造,从工厂建模,工艺建模,柔性制造,精益制造,生产管控,库存,质量等多方面讲述智能制造的落地方案。
  • 破解PCB制造痛点,盘古信息IMS MOM 铸就数字化标杆工厂
  • PL/SQL
  • 开疆智能ModbusRTU转Profinet网关连接西门子CP341配置案例
  • DDD之整体设计流程(2)
  • debian系统分卷是不会影响系统启动速度?
  • 排序算法 (Sorting Algorithms)-Python示例
  • Android 系统架构
  • 阿里云 API 网关 x OKG:游戏连接治理的「最后一公里」
  • 阿里云正式开源 LoongSuite:打造 AI 时代的高性能低成本可观测采集套件
  • 电脑不小心误删了文件怎么恢复??
  • AI资讯日报 - 2025年07月28日
  • EXCEL批量生成超链接引用无效的情况
  • Kotlin中Flow