Java设计模式之工厂模式篇 (转)[@more@]Java设计模式之工厂模式篇
作者:冯睿  本文选自:赛迪网 2003年03月07日
.NET.com.cn/servlets/ad?Pool=tech_pip" frameBorder=0 noResize width=360 scrolling=no height=300>在面向对象的编程中,工厂模式是一种经常被使用到的模式。根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。

工厂模式的原理

为了理解工厂模式是如果工作的,让我们来看一下图一:

图1 工厂模式的工作原理

在图1中,X是基类,Xy和Xz继承了X类。而工厂类能够根据程序传递给它的数据决定生成那一个子类的实例。在右边定义了一个getClass方法,该方法需要参数a并返回一个X类的实例。对于程序员来说,返回的究竟是Xy还是Xz的实例并不重要,因为它们有相同的方法,只不过这些方法的内部实现不同罢了。

一个简单的例子

在什么情况下会使用到工厂模式呢?让我们来看一个简单的例子。在一些网上的调查表中,经常要求填写姓名。有些人填写时姓放在前面,名放在后面(例如中国人填写姓名的习惯);而有些人填写时采用"名,姓"或者"姓,名"的格式(西方大多数文化中都这样填写姓名)。现在让我们假设通过判断姓名中是否包含了","和空格就可以判断到底是姓在前面还是名在前面。下面然我们先定义一个基类Namer:

class Namer { protected String last; //姓 protected String first; //名 public String getFirst() { return first; } public String getLast() { return last; } }

在基类中我们将姓和名保存在两个不同的变量中,并且提供了getFirst()和getLast()方法。由于子类需要使用到保存姓名的变量,因此我们将它们设定为Protected。

现在我们可以实现两个类来区分上面提到的两种情况。在WithoutComma类中,我们假设如果读入字符串中没有空格,则第一个字符是姓,剩下的字符是名;否者第一个空格之前是名,其后是姓:

class WithoutComma extends Namer { public WithoutComma(String s) { int i = s.lastIndexOf(" "); if (i > 0) { // 空格左边是名 first = s.substring(0, i).trim(); // 空格右边是姓 last =s.substring(i+1).trim(); } else { // 没有空格,则第一个字符是姓,以后的字符是名 last = s.substring(0,1); first = s.substring(1).trim(); } } }

对于姓名中包含逗号的情况,代码如下。

class WithComma extends Namer { public WithComma (String s) { int i = s.indexOf(","); if (i > 0) { // 逗号左边的是姓 last = s.substring(0, i).trim(); // 都号右边的是名 first = s.substring(i + 1).trim(); } else { // 没有逗号,将字符串作为名,姓设为空 last = s; first = ""; } } }

接下来就需要实现工厂类了。在工厂类中,我们只需要根据输入的名称中是否带有逗号来生成不同的类的实例。

class NameFactory { public Namer getNamer(String entry) { int i = entry.indexOf(","); //检测是否存在"," if (i>0) return new WithComma(entry); else return new WithoutComma (entry); } }

我们可已通过图二中的例子来看一看在程序中如何使用工厂类:

图2 工厂模式测试程序

在程序中,首先需要初始化工厂类:

NameFactory nfactory = new NameFactory();

然后当"获得姓名"按钮被按下以后,调用computeName()方法,而该方法又调用工厂类的getNamer()方法获得Namer的实例,并将姓和名显示在相应的文本框中:

Namer nmr; nmr = nf.getNamer(jTextFieldName.getText()); jTextFieldFirstName.setText(nmr.getFirst()); jTextFieldLastName.setText(nmr.getLast());

程序的源代码如下:

public class Test extends javax.swing.JFrame { private NameFactory nf; public Test() { nf = new NameFactory(); initComponents(); } private void initComponents() { jPanel1 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); jTextFieldName = new javax.swing.JTextField(); jPanel3 = new javax.swing.JPanel(); jPanel4 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); jTextFieldLastName = new javax.swing.JTextField(); jLabelFirstName = new javax.swing.JLabel(); jTextFieldFirstName = new javax.swing.JTextField(); jPanel5 = new javax.swing.JPanel(); jPanel6 = new javax.swing.JPanel(); jButtonCompute = new javax.swing.JButton(); jButtonClear = new javax.swing.JButton(); jButtonExit = new javax.swing.JButton(); setTitle("u5de5u5382u6a21u5f0fu6d4bu8bd5u7a0bu5e8f"); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); jPanel1.setLayout(new java.awt.GridLayout(5, 1)); jPanel2.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout()); jLabel1.setText("u8f93u5165u59d3u540d"); jPanel2.add(jLabel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(50, 20, -1, -1)); jTextFieldName.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jTextFieldNameActionPerformed(evt); } }); jPanel2.add(jTextFieldName, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 10, 150, 40)); jPanel1.add(jPanel2); jPanel1.add(jPanel3); jPanel4.setLayout(new java.awt.GridLayout(2, 2)); jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabel2.setText("u59d3:"); jPanel4.add(jLabel2); jPanel4.add(jTextFieldLastName); jLabelFirstName.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabelFirstName.setText("u540d:"); jLabelFirstName.setToolTipText("null"); jPanel4.add(jLabelFirstName); jPanel4.add(jTextFieldFirstName); jPanel1.add(jPanel4); jPanel1.add(jPanel5); jButtonCompute.setText("u83b7u5f97u59d3u540d"); jButtonCompute.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonComputeActionPerformed(evt); } }); jPanel6.add(jButtonCompute); jButtonClear.setText("u6e05u7a7a"); jButtonClear.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonClearActionPerformed(evt); } }); jPanel6.add(jButtonClear); jButtonExit.setText("u9000u51fa"); jButtonExit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonExitActionPerformed(evt); } }); jPanel6.add(jButtonExit); jPanel1.add(jPanel6); getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); pack(); } private void jButtonComputeActionPerformed(java.awt.event.ActionEvent evt) { Namer nmr; nmr = nf.getNamer(jTextFieldName.getText()); jTextFieldFirstName.setText(nmr.getFirst()); jTextFieldLastName.setText(nmr.getLast()); } private void jButtonExitActionPerformed(java.awt.event.ActionEvent evt) { System.exit(0); } private void jButtonClearActionPerformed(java.awt.event.ActionEvent evt) { jTextFieldName.setText(""); jTextFieldFirstName.setText(""); jTextFieldLastName.setText(""); } private void jTextFieldNameActionPerformed(java.awt.event.ActionEvent evt) { } private void exitForm(java.awt.event.WindowEvent evt) { System.exit(0); } public static void main(String args[]) { new Test().show(); } private javax.swing.JPanel jPanel6; private javax.swing.JPanel jPanel5; private javax.swing.JButton jButtonExit; private javax.swing.JPanel jPanel4; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel1; private javax.swing.JButton jButtonClear; private javax.swing.JTextField jTextFieldName; private javax.swing.JTextField jTextFieldLastName; private javax.swing.JButton jButtonCompute; private javax.swing.JTextField jTextFieldFirstName; private javax.swing.JLabel jLabelFirstName; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel1; }

通过上面的例子我们可以看到工厂模式中最基本的开发过程。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

工厂模式的适用范围

当遇到下面的情况时,开发人员可以考虑采用工厂模式:

· 在编码时不能预见需要创建哪一种类的实例。

· 一个类使用它的子类来创建对象。

· 开发人员不希望创建了哪个类的实例以及如何创建实例的信息暴露给外部程序。

除了上面提到的例子,工厂模式的实现方式还允许有一些小小的变化,例如:

· 基类可以是一个抽象类,在这种情况下,工厂类必须返回一个非抽象类。

· 基类提供了一些缺省方法,只有当这些缺省方法不能满足特殊需求的情况下才在子类中重写这些方法。

· 可以直接通过传递给工厂类的参数决定应该返回哪一个子类的实例。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-956752/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752043/viewspace-956752/

Java设计模式之工厂模式篇 (转)相关推荐

  1. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  2. Java设计模式之工厂模式 (工厂方法模式)

    上一篇我们学习了简单工厂模式,最后对于增加新产品的缺点,我们在工厂方法模式中解决. 为学习简单工厂模式的小伙伴点击这里Java 设计模式之工厂模式(简单工厂模式) 工厂方法模式要点: 避免简单工厂模式 ...

  3. Java设计模式(工厂模式>抽象工厂模式和原型模式)

    Java设计模式Ⅱ 1.工厂模式 1.1 简单工厂模式 1.2 工厂方法模式 2.抽象工厂模式 3.总结 4.原型模式 4.1 原型模式 4.2 浅拷贝 4.3 深拷贝 5.建造者模式 1.工厂模式 ...

  4. java设计模式之工厂模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

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

    前一阵子学习了Java 中据说是最简单的设计模式的 单例模式,想一起讨论学习的小伙伴请点击这里: Java 设计模式之单例模式 那么今天就把学习的工厂模式记录下来 工厂模式: 实现了创建者和调用者的分 ...

  6. 【JAVA进阶系列】JAVA 设计模式 -- 抽象工厂模式(Abstract Factory)

    [JAVA进阶系列]JAVA 设计模式 -- 抽象工厂模式(Abstract Factory) [1.1]抽象工厂模式简介 抽象工厂者模式的类结构图 AbstractProduct(抽象产品),Abs ...

  7. JAVA设计模式之工厂模式讲解

    目录 前言 开始表演 前言 Java中使用工厂模式的主要原因是为了实现代码的灵活性和可维护性.工厂模式是一种创建型设计模式,它提供了一种将对象的创建和使用进行分离的方式.具体来说,工厂模式可以将对象的 ...

  8. 从零开始学习Java设计模式 | 创建型模式篇:抽象工厂模式

    在本讲,我们来学习一下创建型模式里面的第三个设计模式,即抽象工厂模式. 前言 前面介绍的工厂方法模式中考虑的是一类产品,如畜牧场只养动物.电视机厂只生产电视机(不生产空调.冰箱等其它的电器).计算机学 ...

  9. Java设计模式:工厂模式

    问题提出 Java的工厂模式与现实生活中的工厂的模型是很相似的.工厂是用来做什么?当然是用来生成产品.因此在Java的工厂模式的关键点就是如何描述好产品和工厂这2个角色之间的关系. 下面来仔细描述一下 ...

最新文章

  1. Node.js webpack-dev-server配置命令的两种方式
  2. 分水岭算法及相应处理
  3. (干货)构建镜像之docker commit
  4. javaweb学习总结(二十六)——jsp简单标签标签库开发(二)
  5. 记录”limxml2剖析:功能特性”之摘抄
  6. 使用MQTT.fx接入阿里云物联网平台
  7. qt按钮禁用和激活禁用_为什么试探法只是经验法则:禁用按钮的情况
  8. LoRa和ZigBee谁更适合智能家居?
  9. 《大数据》第1期“专题”——大数据与高性能计算
  10. C99中的变长数组(VLA)
  11. WARNING:Result from SERVER not valid. Partial Result:
  12. hashmap中的key是有序的么_深入理解HashMap遍历元素的顺序
  13. Eclipse中的快捷键……希望朋友们能熟练使用
  14. Spring整合JavaMail
  15. 微软api的word在线预览
  16. 使用 rem 布局的优缺点?
  17. MyBatis批量插入几千条数据,请慎用foreach
  18. Java通过mysql-connector-java-8.0.11连接MySQL Server 8.0遇到的问题
  19. 计算机操作系统 共享性,计算机操作系统的功能和分类探析
  20. channel练习题

热门文章

  1. CHECKBOX用法
  2. 多项式计算秦九韶算法
  3. 怎么学好计算机专业?
  4. 【???】【???】小麦亩产一百八
  5. JavaWeb学习笔记(狂神版)--- 第九节 Cookie与Session
  6. 商汤科技2018年校招
  7. centos 磁盘分区
  8. Sora —— 高性能可编程无线电系统
  9. 基于CloudSim 的云资源调度系统分析设计与实现——合肥工业大学云计算课程作业
  10. Backtrader(十四)- Order订单 - 订单有效期与涨停跌停