一. 定义与类型

定义:有工程对象决定创建出哪一种产品类的实例

类型:创建型,但不属于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设计模式学习——简单工厂的更多相关文章

  1. (@WhiteTaken)设计模式学习——简单工厂

    最近工作比较忙,所以没有怎么写博客,这几天将集中学习一下(厉风行)讲解的设计模式的相关知识,并对主要的代码进行介绍. 言归正传,接下来介绍最简单也是最基础的简单工厂设计模式. 什么是简单工厂? 简单工 ...

  2. Java设计模式之简单工厂、工厂方法和抽象工厂

    在前面的学习中(参见前面的博客),我们学到了很多OO原则: 封装变化 多用组合,少用继承 针对接口/超类编程,不针对实现编程 松耦合 开闭原则 让我们从一个简单的类开始,看看如何将之改造成符合OO原则 ...

  3. Java 设计模式01 - 简单工厂模式

    先要学习设计模式之前的先看看一些基础 UML类图简单说明 可以先看看我的这篇博客: UML类图简单说明,学习编程思路的必会技能 接下来才是重点,开始我们的旅程吧. 一.UML类图展示 我们要用简单工厂 ...

  4. Java设计模式学习之工厂模式

    在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了.Java 设计模式之工厂模式 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低 ...

  5. Java设计模式之简单工厂设计模式

    简单工厂将业务逻辑部分和界面逻辑部分分离开来,降低了界面逻辑和业务逻辑的耦合度,符合面向对象迪米特法则.下面以一个加法减法运算器为例,各位读者可以自行按照这种设计方式设计出一个小小的运算器. 1.业务 ...

  6. (1)java设计模式之简单工厂模式

    一:简单工厂模式的优点          --->在阎宏博士的<JAVA与模式>一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Fa ...

  7. java设计模式之简单工厂模式

    简单工厂: 简单工厂的优点: 1.去除客户端与具体产品的耦合,在客户端与具体的产品中增加一个工厂类,增加客户端与工厂类的耦合 2.封装工厂类,实现代码平台的复用性,创建对象的过程被封装成工厂类,可以多 ...

  8. Java设计模式(1)——简单工厂模式

    简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式.通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 一.模式中包含的角色及其职责 1.工厂(Creator)角色 简单 ...

  9. Java 设计模式之 简单工厂模式(静态工厂方法模式)

    简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的 ...

随机推荐

  1. iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...

  2. springIOC源码解析之Bean的创建

    上一篇讲到了beanFactory的配置文件的解析和beanFactory的创建,都集中到了obtainFreshBeanFactory();这一句代码里了,本篇主要讲bean的创建过程 public ...

  3. 60个DevOps开源工具,你在用哪些?

    你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的.这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 DevOps. 一.开发工具 版本控制&协作开发 1.版 ...

  4. 洛谷 P1892 [BOI2003]团伙(并查集)

    嗯... 题目链接:https://www.luogu.org/problemnew/show/P1892 通过读题可以很清楚的发现这是一个并查集的题,并且要有两个集合: 若他们p和q是朋友,则存入第 ...

  5. python基础 3.0 file 读取文件

    一.python  文件访问 1.在python中要访问文件,首先要打开文件,也就是open r:  只读 w:  只写 ,文件已存在则清空,不存在则创建 a:追加 ,写到文件末尾.如果文件存在,则在 ...

  6. myeclipse svn 在线安装

    https://www.cnblogs.com/sxdcgaq8080/p/6000446.html http://subclipse.tigris.org/update_1.8.x

  7. jdk tomcat

    vi /etc/profile export JAVA_HOME=/usr/java/jdk1.8.0_121export JRE_HOME=/usr/java/jdk1.8.0_121/jreexp ...

  8. JavaScript 获取 Url 上的参数(QueryString)值

    获取URL里面传的参数,在Js中不能像后台一样使用Request.QueryString来获取URL里面参数,下面介绍两种方式用来获取参数 方式一:使用split分隔来获取,这种方法考试了地址中包含了 ...

  9. mysql 位操作支持

    mysql 支持位操作. & 位与 | 位或 例如:update car_ins_fee_entity set change_status=(change_status | 1) where ...

  10. 机器学习框架ML.NET学习笔记【2】入门之二元分类

    一.准备样本 接上一篇文章提到的问题:根据一个人的身高.体重来判断一个人的身材是否很好.但我手上没有样本数据,只能伪造一批数据了,伪造的数据比较标准,用来学习还是蛮合适的. 下面是我用来伪造数据的代码 ...