>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 32426 个阅读者 刷新本主题
 * 贴子主题:  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开发-->Web运作原理(Ⅳ)
  Java网络编程-->自定义JSP标签(Ⅱ)
  精通Spring-->JPA API的高级用法
  Vue3开发-->第一个helloapp应用
  TCP、UDP及Socket代码示例
  ThreadLocal的内存泄露的原因分析以及如何避免
  Java虚拟机(JVM)参数配置说明
  HashMap中 get 和 put 操作的具体过程
  内部类的编程练习题
  Java设计模式中的工厂模式和策略模式范例
  Eclipse的安装配置
  NoClassDefFoundError和ClassNotFoundException的区别
  超详细的Java运算符修炼手册(优秀程序员不得不知道的运算技...
  好消息:《Java网络编程核心技术详解》出版
  Eclipse使用指南:Debug 配置
  JAVA日期加减运算
  通过java.net.URL类连接HTTP服务器时获取响应结果的头部信息
  Java入门实用代码:删除一个文件目录
  初学者该学哪种编程语言
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


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