Java设计模式学习——简单工厂
一. 定义与类型
定义:有工程对象决定创建出哪一种产品类的实例
类型:创建型,但不属于GOF23中设计模式
二. 适用场景
工厂类负责创建的对象比较少
客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心
三. 优点与缺点
优点:只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节
缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则
四. coding
/**
* @program: designModel
* @description: 视频类
* @author: YuKai Fan
* @create: 2018-11-13 16:46
**/
public abstract class Video {
public abstract void product();
}
/**
* @program: designModel
* @description: java视频类
* @author: YuKai Fan
* @create: 2018-11-13 16:47
**/
public class JavaVideo extends Video {
public void product() {
System.out.println("录制java课程视频");
}
}
/**
* @program: designModel
* @description: Python视频类
* @author: YuKai Fan
* @create: 2018-11-13 16:48
**/
public class PythonVideo extends Video{
public void product() {
System.out.println("录制Python课程视频");
}
}
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-11-13 16:48
**/
public class Test {
public static void main(String[] args) {
/*Video video = new JavaVideo();
video.product();*/
VideoFactory videoFactory = new VideoFactory();
Video java = videoFactory.getVideo("java");
if (java == null) {
return;
}
java.product();
}
}
这样,应用层(客户端)只需要传入需要的类型,就可以得到相应的类型视频,不知道创建的细节,UML类图为

但是,如果要新增加一个课程的话,就必须在原有的基础上修改代码,这样违背了设计原则的开闭原则
可以对上面的代码进行一定的改进,通过反射的方法来完成类型的选择
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-11-13 16:50
**/
public class VideoFactory {
public Video getVideo(Class c) {
Video video = null;
try {
video = (Video) Class.forName(c.getName()).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return video;
} /*public Video getVideo(String type) { if ("java".equalsIgnoreCase(type)) {
return new JavaVideo(); } else if ("python".equalsIgnoreCase(type)) {
return new PythonVideo(); }
return null;
}*/
}
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-11-13 16:48
**/
public class Test {
public static void main(String[] args) {
/*Video video = new JavaVideo();
video.product();*/
/*VideoFactory videoFactory = new VideoFactory();
Video java = videoFactory.getVideo("java");
if (java == null) {
return;
}
java.product();*/
VideoFactory videoFactory = new VideoFactory();
Video java = videoFactory.getVideo(JavaVideo.class);
if (java == null) {
return;
}
java.product();
}
}
这样的好处是,应用层(客户端)直接传入对应的视频类class即可,不需要修改工厂类的代码
五. 源码分析 jdk源码解析
在jdk中使用简单工厂的体现:
1.calender.java中的getInstance方法中的createCalender方法
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;
//这里使用的就是简单工厂模式,switch-case判断返回相应的国家日期类型
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
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-else判断返回相应的国家日期类型
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;
}
这个类的UML为:

jdbc中的加载驱动,获取连接,也是用的简单工厂模式
Java设计模式学习——简单工厂的更多相关文章
- (@WhiteTaken)设计模式学习——简单工厂
最近工作比较忙,所以没有怎么写博客,这几天将集中学习一下(厉风行)讲解的设计模式的相关知识,并对主要的代码进行介绍. 言归正传,接下来介绍最简单也是最基础的简单工厂设计模式. 什么是简单工厂? 简单工 ...
- Java设计模式之简单工厂、工厂方法和抽象工厂
在前面的学习中(参见前面的博客),我们学到了很多OO原则: 封装变化 多用组合,少用继承 针对接口/超类编程,不针对实现编程 松耦合 开闭原则 让我们从一个简单的类开始,看看如何将之改造成符合OO原则 ...
- Java 设计模式01 - 简单工厂模式
先要学习设计模式之前的先看看一些基础 UML类图简单说明 可以先看看我的这篇博客: UML类图简单说明,学习编程思路的必会技能 接下来才是重点,开始我们的旅程吧. 一.UML类图展示 我们要用简单工厂 ...
- Java设计模式学习之工厂模式
在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了.Java 设计模式之工厂模式 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低 ...
- Java设计模式之简单工厂设计模式
简单工厂将业务逻辑部分和界面逻辑部分分离开来,降低了界面逻辑和业务逻辑的耦合度,符合面向对象迪米特法则.下面以一个加法减法运算器为例,各位读者可以自行按照这种设计方式设计出一个小小的运算器. 1.业务 ...
- (1)java设计模式之简单工厂模式
一:简单工厂模式的优点 --->在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Fa ...
- java设计模式之简单工厂模式
简单工厂: 简单工厂的优点: 1.去除客户端与具体产品的耦合,在客户端与具体的产品中增加一个工厂类,增加客户端与工厂类的耦合 2.封装工厂类,实现代码平台的复用性,创建对象的过程被封装成工厂类,可以多 ...
- Java设计模式(1)——简单工厂模式
简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式.通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 一.模式中包含的角色及其职责 1.工厂(Creator)角色 简单 ...
- Java 设计模式之 简单工厂模式(静态工厂方法模式)
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的 ...
随机推荐
- iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...
- springIOC源码解析之Bean的创建
上一篇讲到了beanFactory的配置文件的解析和beanFactory的创建,都集中到了obtainFreshBeanFactory();这一句代码里了,本篇主要讲bean的创建过程 public ...
- 60个DevOps开源工具,你在用哪些?
你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的.这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 DevOps. 一.开发工具 版本控制&协作开发 1.版 ...
- 洛谷 P1892 [BOI2003]团伙(并查集)
嗯... 题目链接:https://www.luogu.org/problemnew/show/P1892 通过读题可以很清楚的发现这是一个并查集的题,并且要有两个集合: 若他们p和q是朋友,则存入第 ...
- python基础 3.0 file 读取文件
一.python 文件访问 1.在python中要访问文件,首先要打开文件,也就是open r: 只读 w: 只写 ,文件已存在则清空,不存在则创建 a:追加 ,写到文件末尾.如果文件存在,则在 ...
- myeclipse svn 在线安装
https://www.cnblogs.com/sxdcgaq8080/p/6000446.html http://subclipse.tigris.org/update_1.8.x
- jdk tomcat
vi /etc/profile export JAVA_HOME=/usr/java/jdk1.8.0_121export JRE_HOME=/usr/java/jdk1.8.0_121/jreexp ...
- JavaScript 获取 Url 上的参数(QueryString)值
获取URL里面传的参数,在Js中不能像后台一样使用Request.QueryString来获取URL里面参数,下面介绍两种方式用来获取参数 方式一:使用split分隔来获取,这种方法考试了地址中包含了 ...
- mysql 位操作支持
mysql 支持位操作. & 位与 | 位或 例如:update car_ins_fee_entity set change_status=(change_status | 1) where ...
- 机器学习框架ML.NET学习笔记【2】入门之二元分类
一.准备样本 接上一篇文章提到的问题:根据一个人的身高.体重来判断一个人的身材是否很好.但我手上没有样本数据,只能伪造一批数据了,伪造的数据比较标准,用来学习还是蛮合适的. 下面是我用来伪造数据的代码 ...