>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 32427 个阅读者 刷新本主题
 * 贴子主题:  JDK中的工厂设计模式 回复文章 点赞(0)  收藏  
作者:javathinker    发表时间:2019-04-03 22:46:43     消息  查看  搜索  好友  复制  引用

本文通过介绍JDK源码中用到的工厂方法深入理解一下工厂方法。

如果抛开设计模式的范畴,“工厂方法”这个词也可以指作为“工厂”的方法,这个方法的主要目的就是创建对象,而这个方法不一定在单独的工厂类中。这些方法通常作为静态方法,定义在方法所实例化的类中。

每个工厂方法都有特定的名称。在许多面向对象的编程语言中,构造方法必须和它所在的类具有相同的名称,这样的话,如果有多种创建对象的方式(重载)就可能导致歧义。工厂方法没有这种限制,所以可以具有描述性的名称。举例来说,根据两个实数创建一个复数,而这两个实数表示直角坐标或极坐标,如果使用工厂方法,方法的含义就非常清晰了。当工厂方法起到这种消除歧义的作用时,构造方法常常被设置为私有方法,从而强制客户端代码使用工厂方法创建对象。
class Complex {
     public static Complex fromCartesianFactory(double real, double imaginary) {
         return new Complex(real, imaginary);
     }
     public static Complex fromPolarFactory(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }
     private Complex(double a, double b) {
         //...
     }
}

Complex product = Complex.fromPolarFactory(1, pi);

上面的代码也可以叫做使用了工厂方法模式。同样是定义了一个工厂方法,方法的作用就是生成一个新的对象。

JDK中的工厂方法模式

什么情况下应该使用工厂方法模式?

其实这个问题很简单。很多时候我们在自己的代码中会不自觉的会使用到工厂方法模式。考虑以下情况:

创建对象需要大量重复的代码。
创建对象需要访问某些信息,而这些信息不应该包含在复合类中。
创建对象的生命周期必须集中管理,以保证在整个程序中具有一致的行为。

遇到上面的情况时,你是不是会”很自觉”的把创建对象的代码封装到一个方法中呢?这个方法就是工厂方法。其实这就是工厂方法的思想。

在JDK中,也有很多使用工厂方法模式的代码。下面就介绍几个典型的用法。

Collection中的iterator方法

java.util.Collection接口中定义了一个抽象的iterator()方法,该方法就是一个工厂方法。

对于iterator()方法来说Collection就是一个根抽象工厂,下面还有List等接口作为抽象工厂,再往下有ArrayList等具体工厂。

java.util.Iterator接口是根抽象产品,下面有ListIterator等抽象产品,还有ArrayListIterator等作为具体产品。

使用不同的具体工厂类中的iterator方法能得到不同的具体产品的实例。

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

JDBC数据库开发

在使用JDBC进行数据库开发时,如果数据库由MySQL改为Oracle或其他,则只需要改一下数据库驱动名称就可以,其他都不用修改(前提是使用的都是标准SQL语句)。或者在Hibernate框架中,更换数据库方言也是类似道理。

连接邮件服务器框架

如果需要设计一个连接邮件服务器的框架,那么就要考虑到连接邮件服务器有几种方式:POP3、SMTP、HTTP。就可以定义一个连接邮件服务器接口,在此接口中定义一些对邮件操作的接口方法,把这三种连接方式封装成产品类,实现接口中定义的抽象方法。再定义抽象工厂和具体工厂,当选择不同的工厂时,对应到产生相应的连接邮件产品对象。采用这种工厂方法模式的设计,就可以做到良好的扩展性。比如某些邮件服务器提供了WebService接口,只需要增加一个产品类和工厂类就可以了,而不需要修改原来代码。

其他工厂方法

除上面介绍的典型的使用工厂方法模式的用法外,在JDK中还有几处使用了工厂方法来创建对象。其中包括:
java.lang.Proxy#newProxyInstance()
java.lang.Object#toString()
java.lang.Class#newInstance()
java.lang.reflect.Array#newInstance()
java.lang.reflect.Constructor#newInstance()
java.lang.Boolean#valueOf(String)
java.lang.Class#forName()

读者感兴趣可以找出来看一看,这些方法都是用于返回具体对象。上面大部分方法都和反射有关,因为反射创建对象的过程比较复杂,封装成工厂方法更易于使用。



程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->接口
  JavaWeb开发-->类的生命周期
  JSP与Hibernate开发-->JSP中使用JavaBean(Ⅱ)
  Java网络编程-->Web运作原理(Ⅳ)
  精通Spring-->域对象在持久化层的四种状态
  Vue3开发-->持久化层的映射类型
  快速理解 函数式编程,响应式编程,链式编程
  BIO、NIO和AIO的区别、三种IO的原理与用法
  BIO和NIO区别
  NIO模式的IO多路复用底层原理
  Java虚拟机(JVM)参数配置说明
  Java Optional 解决空指针异常总结
  不修改源代码,动态注入Java代码的方法
  java NIO示例以及流程详解
  Synchronized与ReentrantLock区别总结
  Java读取大文件的高效率实现_java大文件
  Java设计模式:备忘录模式
  Java设计模式:享元模式
  redis持久化问题处理
  Java入门实用代码:100以内整数求和运算
  Java线程实现龟兔赛跑
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。