三种工厂模式的详解:

简单工厂模式:
  适用场景:工厂类负责创建的对象较少,客户端只关心传入工厂类的参数,对于如何创建对象的逻辑不关心

  缺点:如果要新加产品,就需要修改工厂类的判断逻辑,违背软件设计中的开闭原则,且产品类多的话,就会使得简单工厂类比较复杂

  在jdk源码中的具体实例(注意看代码中的中文注释)
    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) {
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 (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;
}
  除了日历类还有JDBC,当我们需要MySQL数据库的驱动时,我们就传MySQL的参数,用Oracle的就传相应的参数
 
工厂方法模式:
 
  适用场景:创建对象需要大量重复代码,客户端不依赖与产品类实例如何被创建实现等细节,一个类通过其子类来指定创建哪个对象
  工厂方法的核心在于把实例化过程放在子类中进行(这是和简单工厂一个区别比较大的地方)
  要解释工厂方法模式,要有下面的概念:一个总的抽象工厂及抽象工厂的子类还有一个抽象的产品类与抽象产品类的子类,具体看下面的jdk源码:

拿其中ArrayList实现的iterator()方法来看

public Iterator<E> iterator() {
return new Itr();
} /**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount; public boolean hasNext() {
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}

  可以这样理解:Collection接口里面定义了许多方法就像size(),isEmpty(),iterator()等等这些方法可以认为是工厂里面的产品,Collection可以看作是一个总的抽象工厂。它的一些实现这个接口的类,像ArrayList,LinkedHashSet等等可以看作一个个不同的品牌的工厂,而总的产品Iterator接口里面会定义产品所需功能的细节,然后在交给各个品牌不同的工厂来实现。

抽象工厂模式:

  看懂上面的之后就特别好理解抽象工厂,抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;(比如Iterator()方法的不同实现)而抽象工厂模式则需要面对多个产品等级结构(Collection接口下的不同方法)。再说明白一点就是:Collection就是一个抽象工厂,它提供了一个产品类的库,所有产品都以同样接口出现,从而使客户端不依赖于具体实现。工厂方法则是抽象工厂里面的其中一个产品类,并且把这个方法的实例化放入具体的实现类中

结合JDK源码看设计模式——简单工厂、工厂方法、抽象工厂的更多相关文章

  1. 结合JDK源码看设计模式——单例模式

    定义: 保证一个类仅有一个实例,并提供一个全局访问点 适用场景: 确保任何情况下这个对象只有一个实例 详解: 私有构造器 单利模式中的线程安全+延时加载 序列化和反序列化安全, 防止反射攻击 结合JD ...

  2. 结合JDK源码看设计模式——桥接模式

    前言: 在我们还没学习框架之前,肯定都学过JDBC.百度百科对JDBC是这样介绍的[JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Jav ...

  3. 结合JDK源码看设计模式——原型模式

    定义: 指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.不需要知道任何创建的细节,不调用构造函数适用场景: 类初始化的时候消耗较多资源 new产生的对象需要非常繁琐的过程 构造函数比较 ...

  4. 结合JDK源码看设计模式——模板方法模式

    前言: 相信很多人都听过一个问题:把大象关进冰箱门,需要几步? 第一,把冰箱门打开:第二,把大象放进去:第三,把冰箱门关上.我们可以看见,这个问题的答案回答的很有步骤.接下来我们介绍一种设计模式--模 ...

  5. 结合JDK源码看设计模式——迭代器模式

    前言: Iterator翻译过来就是迭代器的意思.在前面的工厂模式中就介绍过了iterator,不过当时介绍的是方法,现在从Iterator接口的设计来看,似乎又是一种设计模式,下面我们就来讲讲迭代器 ...

  6. 结合JDK源码看设计模式——适配器模式

    定义: 将一个类的接口转换成客户期望的另外一个接口(重点理解适配的这两个字),使得接口不兼容的类可以一起工作适用场景: 已经存在的类,它的方法和需求不匹配的时候 在软件维护阶段考虑的设计模式 详解 首 ...

  7. 结合JDK源码看设计模式——建造者模式

    概念: 将一个复杂对象的构建与它的表示分离.使得同样构建过程可以创建不同表示适用场景: 一个对象有很多属性的情况下 想把复杂的对象创建和使用分离 优点: 封装性好,扩展性好 详解: 工厂模式注重把这个 ...

  8. 结合JDK源码看设计模式——享元模式

    前言 在说享元模式之前,你一定见到过这样的面试题 public class Test { public static void main(String[] args) { Integer a=Inte ...

  9. 结合JDK源码看设计模式——观察者模式

    前言: 现在我们生活中已经离不开微信,QQ等交流软件,这对于我们来说不仅是交流,更有在朋友圈中或空间中进行分享自己的生活,同时也可以通过这个渠道知道别人的生活.我们在看朋友圈的时候其实我们扮演的就是一 ...

随机推荐

  1. unittest生产html测试报告

    需要添加HTMLTestRunner.py文件,我用的ubuntu16.04下的python3.5.2,所以我放在/usr/lib/python3.5下 import unittest import ...

  2. linux下SS 网络命令详解

    ss命令用来显示处于活动状态的套接字信息. ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容. 但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比n ...

  3. FTP出现PORT模式成功, 请更新你的站点配置文件

    最近用FTP连接站点,经常出现连接不上或者连接失败,提示以PASV模式连接失败,正在使用PORT模式连接,最后才能连接成功,连接时间也是相当长,又慢又不稳定.   工具/原料   FlashFXP等F ...

  4. VsCode 使用专用编程字体FiraCode

    FiraCode资料:https://github.com/tonsky/FiraCode PHP代码效果如下: VsCode 配置中添加: "editor.fontFamily" ...

  5. Android 实现卡片翻转的动画(翻牌动画)

    Android 实现卡片翻转的动画(翻牌动画) 需求描述 点击卡片,卡片翻转过来显示内容. 点击左边的卡片,将卡片翻转显示右边的图片结果. 功能实现 因为要翻转所以使用动画来完成翻转的动画.动画分为两 ...

  6. ubuntu配置https

    # 重定向 http 到 https server { listen 80; server_name www.domain.com; rewrite ^(.*)$ https://$server_na ...

  7. controller分支实现前台显示弹框同时转发

    controller分支实现前台显示弹框,前台不需要进行什么操作,  前台请求后台的分支即可. controller层(标红的地方是(alert('账号或密码错误!请重新输入!!!!')        ...

  8. python编程实战

    1.计算对称平方数 题目描述 打印所有不超过n(n<256)的,其平方具有对称性质的数,如11*11=121. 输入描述 无 输出描述 每行一个数,表示对称平方数 def f(n): flag ...

  9. 用CSS实现一个抽奖转盘

    效果 基本是用CSS实现的,没有用图片,加一丢丢JS.完全没有考虑兼容性. 首先画一个转盘, <!DOCTYPE html> <html lang="en"> ...

  10. 【Spark篇】---Spark初始

    一.前述 Spark是基于内存的计算框架,性能要优于Mapreduce,可以实现hadoop生态圈中的多个组件,是一个非常优秀的大数据框架,是Apache的顶级项目.One stack  rule  ...