使用 Design Pattern Toolkit 进行模型驱动的开发入门

摘自 IBM WebSphere 开发者技术期刊

引言

当大多数人想到模型驱动的开发时,首先出现在脑海中的是使用某种 UML 模型进行编码以及从该模型生成相应的构件。然而,事情并不总是这样的。模型存在于各种各样的地方。模型是任何驱动产生过程或行为的构件。

模型驱动的开发具有许多目标:

  • 减少在开发常见的构件上耗费的时间。
  • 维护最小限度的信息量。
  • 以一种中立的方式对模型进行维护,这使得从相同的模型生成多种类型的实现和构件成为可能。例如,我们应该可以使用不同的模板从相同的模型中生成 Web UI 和本地的 GUI UI。

本文将通过设计模式工具箱来介绍模型驱动的开发,该工具箱是一种支持 Eclipse 的模板引擎,用来根据可自定义的、模型驱动体系结构转换(JET2 的一种推动技术,请参见参考资料部 分)生成相应的应用程序。我们将介绍设计模式工具箱 (DPTK) 中的代码生成机制的基本知识,与此同时,一并阐述引导您实现模型驱动开发 (MDD)的代码生成方面的一些良好设计。这些设计原则使得 DPTK 不仅仅只是玩具代码生成器,而是一种功能齐全的模型驱动的开发工具,可以生成非常复杂的系统。本文将重点关注于构建模式模板的基本原理。

有关更多的内容或下载设计模式工具箱,请访问 IBM alphaWorks


模式模板

DPTK 中的模式创造者使用标记来构建模式模板。这些标记具有特殊的行为,用来访问模型、执行逻辑并完成各种各样其他的任务。丰富的标记提供了大量的功能,并且实 际上代表了构建任何复杂的 MDD 转换所需的基本构件。模式模板的主要目标是生成相应的构件,然而正如我们将在下一部分中看到的,模式模板可以用来完成更多的任务。

为了能够更好地理解相关内容,让我们先来研究下面简单的模式模板:


图 1. 简单的模式模板

这是一个非常简单的 DPTK 视图:

  1. 该模式应用于简单的 XML 模型。
  2. DPTK 引擎调用了一个模式模板。模式模板使用 DPTK 标记语言替换其中动态的部分。
  3. 并生成最终的构件。

从简单的 XML 声明生成相应的 Java™ 类并不是什么让人激动的事情,但是其目的是为对整个流程进行研究奠定基础。接下来,我们将对其进行更仔细的研究。


用于代码生成的模型-视图-控制器模式

模型-视图-控制器 (MVC) 是一种常用的设计模式,用于构建许多不同类型的应用程序。例如,在 Java EE 中,诸如 JavaServer™ Faces 和 Struts 这样的框架都专门提供了 MVC 设计。MVC 允许应用程序中事务的分离,其中模型代表数据和业务逻辑,视图代表如何观察数据,而控制器则处理用户的输入、模型调用和视图选择。

事实上,MVC 是使用设计模式工具箱构建 MDD 解决方案的一种优秀的设计模式。考虑一下图 2:


图 2. MVC 作为一种设计模式

DPTK 标记库包含各种各样的标记,它们可以用来完成许多任务。因此,我们可以使用特定的角色构建经过精心设计的模板。例如,控制器模式模板将生成许多构件的整体容器,并调用各种其他的模板,而这些模板将生成特定的构件。

通过下面一系列练习,您将可以通过示例了解并掌握如何使用 MVC 设计模式生成相应的构件。您可以在结尾处访问DPTK 并下载本文中的示例资料


构建模式模板

在进行模型驱动的开发的过程中,最好时刻将目标铭记于心。也就是说,手动地构建出第一个案例。这样,您就可以弄清楚究竟需要生成什么样的内容。在开 始这项工作前,我们将向您介绍一个示例样本(在后续的文章中,我们将讨论一些工具,这些工具可以用来对样本进行分析,以便生成模式本身)。在这个示例中, 我们提供了在 IBM Rational® Software Architect 中使用设计模式工具箱的相关说明。然而,也可以使用安装了 DPTK 插件的普通的 Eclipse 轻松地完成这个练习(请参见参考资料部分)。

  1. 启动 Rational Software Architect,并打开一个新的、空的工作区:

    1. 通过选择 Window => Open Perspective => Other(图 3),切换到设计模式工具箱透视图。



      图 3. Open perspective


    2. 从对话框(图 4)中选择 Design Pattern Toolkit



      图 4. Select perspective


  2. 导入我们的示例 Java 样本,这是我们将要生成的 JavaBean 的示例:

    1. 右键单击 Navigator 视图并选择 Import(图 5)。



      图 5. 导入示例


    2. 从导入向导中选择 Project Interchange。(如果您正使用普通的 Eclipse,可以对该项目进行解压,并将其作为一个已有的项目导入到您的工作区。)



      图 6. 导入示例


    3. 导航至下载资料并选择 MyExemplar.zip(图 7)。



      图 7. 选择项目


    4. 选择 MyExemplar 项目,并按 Finish

  3. 检查其中的构件:

    1. 展开该项目(图 8)并打开文件 sample.appdef



      图 8. 打开示例


      这个文件将包含大量的 XML 标记。对于那些熟悉 IBatis(请参见参考资料部分)的读者,您将注意到,这个 XML 模型(清单 1)反映了 iBatis 映射文件的 parameterMap 结构。它定义了 Java 类,以及每个属性的相关属性和数据类型,并且将作为生成过程的模型。

      (请记住,这里的目标是熟悉如何编写模式模板。这里并没有给出维护模型的最佳实践。在实际情况下,输入和内部模型并不匹配。事实上,稍后我们将对内部模型进行修改。)



      清单 1
      				
      <app>
      <parameterMap class="com.ibm.dptk.ibatis.dataobject.Customer"
      id="newCustomerMap" >
      <parameter property="customerId" javaType="java.lang.Integer"/>
      <parameter property="name" javaType="java.lang.String"/>
      <parameter property="address1" javaType="java.lang.String" />
      <parameter property="address2" javaType="java.lang.String" />
      <parameter property="city" javaType="java.lang.String" />
      <parameter property="state" javaType="java.lang.String" />
      <parameter property="zip" javaType="java.lang.String" />
      </parameterMap>
      </app>

    2. 如果打开 Java 类,您将发现一个简单的 JavaBean,它具有一些简单的属性以及相应的 setter 和 getter。在这个练习中,为了方便起见,我们根据 JavaBean 属性以及相应的 getter 和 setter 对其进行分组。这个 JavaBean 如下所示。



      清单 2
      public class Customer implements Serializable {

      private java.lang.String address1;

      /**
      * Gets the address1
      *
      * @return Returns a java.lang.String
      */
      public java.lang.String getAddress1() {
      return address1;
      }

      /**
      * Sets the address1
      *
      * @param java.lang.String
      * The address1 to set
      */
      public void setAddress1(java.lang.String address1) {
      this.address1 = address1;
      }

      ...

上面是一种非常简单的检查目标示例的方法。在许多情况下,模型和生成的构件并不是那么明显。我们将在后续的文章中演示更高级的分析技术,以便对样本进行分析并发现其中的模型。


创建和运行模式

为了使您清楚地了解如何创建和测试模式,现在我们将创建一个模式项目,并将这个模式应用于一个模型。

  1. 创建模式项目。

    1. 右键单击 Navigator 视图并选择 New => New pattern project。(图 9)



      图 9. 创建新的模式


    2. 将该模式命名为 IBatisJavaBeanGenerator,然后按 Next(图 10)。



      图 10. 创建新的模式


    3. 对下列字段进行验证或输入相应的值:

      • Pattern Name:输入模式名称。
      • Pattern ID:唯一模式 ID 值。
      • Appdef Type:保存您的模型的文件扩展名类型。当针对一个模型运行具有这种扩展名的模式时,这个模式将显示可适用于这个模型的模式的列表。
      • Applies To:表示该模型是否在单个文件中,即是否使用单个文件进行代码生成。


      图 11. 创建新的模式


  2. DPTK 设计为使用模型-视图-控制器模式。因此,设计模式工具箱项目向导创建了一个模型-视图-控制器的缺省项目结构。(图 12)



    图 12. MVC 项目结构


    1. 控制器文件夹下的模板将会用来实现生成过程。当您将模式应用于模型时,首先会调用 control.pat 文件。

    2. 在视图文件夹中,模式作者将存储用来表示数据视图的模板。

    3. 这个项目还创建了一个虚拟的 sample.appdef 文件(图 13)。在 Navigator 视图中选择该文件以打开它。



      图 13. 虚拟的 sample.appdef 文件


    4. 图 14 中显示的是一个仅具有简单的 <app> 标记的 sample.appdef 文件。



      图 14. 虚拟的 sample.appdef 文件


    5. DPTK 还提供了简单的视图模板的示例,即 dump.pat 文件(图 15)。



      图 15. 视图模板示例


    6. 如果打开这个 dump.pat 文件,您将发现另一个简单的文件,如清单 3 所示。这个文件采用了内存 (In-memory) 模型,并将其中的内容转储到一个文件中。



      清单 3
      <exists node="/*/.." attr=".encoding">
      <?xml version="1.0" encoding="<attr node="/*/.." name=".encoding"/>"?>
      </exists>
      <exists node="/*/.." attr=".name">
      <!DOCTYPE <attr node="/*/.." name=".name"/> PUBLIC "<attr node="/*/.."
      name=".publicId"/>" "<attr node="/*/.." name=".systemId"/>">
      </exists>
      <dump node="/*" format="true" entities="true"/>

    7. 打开 control.pat 文件。(图 16)



      图 16. 打开 control.pat 文件


    8. 清单 4 显示了 control.pat 文件中的内容。如果查看代码中的粗体部分,您将看到我们使用 <start> 模板标记来调用 dump.pat。这个 start 标记将调用模式模板,并将结果转储到指定的资源,在我们的示例中,是 dump.xml 文件。



      清单 4
      *** High-Level Controller

      *** Apply naming conventions

      <include template="ibatis.java.bean.generator/controller/naming.pat"/>


      *** Derive names and other data

      <include template="ibatis.java.bean.generator/controller/derived.pat"/>




      *** Dump the modified appdef file for testing and debug purposes

      <start template="ibatis.java.bean.generator/view/dump.pat" resource="dump.xml"
      replace="true"/>

  3. 现在我们可以来研究如何调用这些模式。

    1. 右键单击所包含的 sample.appdef 文件,然后选择 Apply Pattern。(图 17)



      图 17. 应用模式


    2. 选择 Ibatis Java Bean Generator 并按 OK。(图 18)



      图 18. 生成模式


    3. 在生成该模式后,您应该看到图 19 中所示的文本框。



      图 19. 成功地应用模式


    4. 您应该还有一个名为 dump.xml 的文件(图 20)。



      图 20. Dump.xml 文件


    5. 如果仔细检查 dump.xml (图 21)的内容,您将发现,它是一个复制了该模型的简单的 XML 文件。(当然这并不是什么非常令人激动的事情,但是对于调试来说却非常有用。)

      图 21. Dump.xml 文件


    6. 如果您感兴趣,可以将 sample.appdef 从样本项目中复制到模式项目,并覆盖缺省的项目。

    7. 重新将该模式应用于 sample.appdef(图 22)。



      图 22. 重新应用模式


    8. 现在,dump.xml 文件应该包含了我们的样本模型。(图 23)



      图 23. Dump.xml 文件






回页首


使用 DPTK 标记创建模式模板

现在可以创建我们的第一个模板了。我们的目标是从 sample.appdef 文件生成一个 JavaBean。

  1. 要生成 Java 源文件,生成过程必须发生在一个 Java 项目中。设计模式工具箱可以生成各种各样的 Eclipse 项目类型,但是考虑到我们的目的,我们将手动地创建一个 Java 项目:

    1. 在设计模式工具箱中选择 File => New=> Project(图 24)。



      图 24. 创建 Java 项目


    2. 选择 Java Project(图 25)。



      图 25. 创建 Java 项目


    3. 将该项目命名为 MyJavaBeanProject,并按 Finish(图 26)。



      图 26. 创建 Java 项目


    4. 当询问是否切换到 Java 透视图时,回答 No(图 27)。



      图 27. 拒绝透视图切换


    5. 将 sample.appdef 文件从样本中复制到这个 Java 项目(图 28)。



      图 28. 复制 sample.appdef 文件


  2. 现在我们将创建一个模式模板。右键单击 view 文件夹,选择 New => File(图 29),并将新的文件命名为 JavaBean.pat(图 30)。



    图 29. 创建模式模板




    图 30. 创建模式模板


  3. 使用 Customer JavaBean 作为起点,将 JavaBean 代码复制到该模板中。从样本项目中复制 Customer.java 代码,并将其粘贴到该模板中。这个 pat 文件应该与图 31 中所示的文件类似。



    图 31. 创建模式模板


  4. 要使 JavaBean 模板成为我们的模式中的一部分,必须将其添加到 control.pat。

    1. 打开 control.pat 文件(图 32)。



      图 32. 打开 control.pat 文件


    2. 添加另一个 start 标记,如清单 5 中的粗体文本所示(或从下载文件的 C:/DPTKArticles/Part1/CodeSnippet1.txt 中进行复制)。template 属性指向 JavaBean.pat 文件。resource 属性定义了文件的名称。(资源文件夹是相对于 Eclipse 项目中指定的 src 目录,而不是项目的根目录,因为文件类型为 java。)



      清单 5
      <start template="ibatis.java.bean.generator/view/dump.pat" resource="dump.xml"
      project="MyJavaBeanProject" replace="true"/>
      <start template="ibatis.java.bean.generator/view/JavaBean.pat"
      resource="com/ibm/dptk/ibatis/dataobject/Customer.java" replace="true"/>

    3. 通过右键单击 MyJavaBeanProject 中的 sample.appdef,应用这个模式(图 33)。



      图 33. 应用模式


    4. 从模式列表中选择 Ibatis Java Bean Generator(图 34),这时应该生成了 Customer 类(图 35)。



      图 34. 应用模式




      图 35. 生成的 Customer 类



使用设计模式工具箱进行构建

现在,我们将使用一些设计模式工具箱标记来构建 JavaBean 模式模板。

  1. 设计模式工具箱中包含一些标记,这些标记允许我们访问模型并使用模式中的数据。第一个标记是访问模型中的属性数据:

    1. 您将从该模型中回忆起用来获取类名的信息(图 36)。现在,打开 JavaBean.pat 文件(图 37)。



      图 36. 打开 JavaBean.pat 文件




      图 37. 打开 JavaBean.pat 文件


    2. 第一个标记是 <attr> 标记,它允许我们访问特定标记中的属性。<attr> 标记还有其他的一些属性,它们允许您以某种方式对文本进行格式化。如图 38 所示,使用清单 6 中的文本替换包名和类名。您还可以从 C:/DPTKArticles/Part1/CodeSnippet2.txt 中复制相应的文本。(另外,下载文件中提供了一个完整的模板,如果您希望加载它。)



      图 38. 替换包名和类名




      清单 6
      package <attr node="/app/parameterMap" name="class" format="QP" />;

      import java.io.Serializable;

      public class <attr node="/app/parameterMap " name="class" format="QC">
      implements Serializable {

  2. 您可以使用标记对模型中的属性数据进行转储。然而,有时可能需要修改内存模型。打开 control.pat 文件(图 39)并检查我们以前添加的 start 模板标记(清单 7)。



    图 39. 打开 control.pat 文件




    清单 7
    <start template="ibatis.java.bean.generator/view/JavaBean.pat" 
    resource="com/ibm/dptk/ibatis/dataobject/Customer.java"
    replace="true"/>

  3. 问题是,我们不能在另一个 DPTK 标记中使用 attr 标记。DPTK 提供了一种可用来访问数据的动态表达式语言。有一个问题是,类的格式需要在一个目录结构中。动态表达式可能会变得很笨拙。解决这个问题的另一种方法是,对 内存模型进行修改。这种方法允许您以不同的方式对相同的数据进行格式化,然后直接访问它。<setAttr> 标记允许您设置现有标记的属性。

    1. 添加清单 8 的粗体文本中的标记(或从 C:/DPTKArticles/Part1/CodeSnippet3.txt 中进行复制)。这里,我们以几种不同的方式对类名进行格式化。



      清单 8
      <setAttr node="/app/parameterMap" name="classname" ><attr node="/app/parameterMap" 
      name="class"></setAttr>
      <setAttr node="/app/parameterMap" name="name" ><attr node="/app/parameterMap"
      name="class" format="QC"></setAttr>
      <setAttr node="/app/parameterMap" name="dir"><attr node="/app/parameterMap" name="class"
      format="PD"></setAttr>
      <setAttr node="/app/parameterMap" name="package"><attr node="/app/parameterMap"
      name="class" format="QP" /></setAttr>



      *** Dump the modified appdef file for testing and debug purposes


      <start template="ibatis.java.bean.generator/view/dump.pat" resource="dump.xml"
      project="MyJavaBeanProject" replace="true"/>
      <start template="ibatis.java.bean.generator/view/JavaBean.pat"
      resource="com/ibm/dptk/ibatis/dataobject/Customer.java" replace="true"/>

    2. 应用该模式,然后查看 dump.xml 文件,它显示了内存模型的情况(图 40)。我们并没有修改原始的输入模型。



      图 40. 内存模型


  4. 现在,我们可以对模板进行修改,以访问新的模型元素:

    1. 修改 resource 属性的值,如下面的粗体文本所示。



      清单 9
      <start template="ibatis.java.bean.generator/view/JavaBean.pat" 
      resource="%/app/parameterMap(dir)%
      .java" replace="true"/>

    2. 如下所示,回到 JavaBean.pat 并修改 attr 标记,以引用模型中新的数据。



      清单 10
      package <attr node="/app/parameterMap" name="package" />;

      import java.io.Serializable;

      public class <attr node="/app/parameterMap" name="name"> implements
      Serializable {

  5. 接 下来,我们需要生成 JavaBean 属性。因为 Java 属性的数目是可变的,所以我们需要对模型进行遍历。设计模式工具箱中具有 iterate 标记。(另外,从 C:/DPTKArticles/Part1/CodeSnippet4.txt 中为这部分内容复制完整的类代码段。)

    1. 打开 the JavaBean.pat 文件。

    2. 我们仅需要一个 Java 属性作为模型。删除第一个属性以外所有的属性。保留 address 属性以及它的 getter 和 setter。

    3. 在清单 11 中添加 iterate 标记,使之包含 Java 属性、getter 和 setter。图 41 演示了这个示例。



      清单 11
      <iterate nodes="/app/parameterMap/parameter" name="currentParameter" >



      图 41. Iterate 标记


    4. 使用下面的标记替换类和属性。可以参考图 42,以了解在何处进行替换。



      清单 12
      private <attr node="currentParameter" name="javaType"/> <attr 
      node="currentParameter" name="name"/>;



      图 42. 替换类型和属性


    5. 最后,如清单 13 中的粗体文本所示,对 setter 和 getter 标记进行更新,并应用该模式(图 43)。



      清单 13
      package <attr node="/app/parameterMap" name="package" />;

      import java.io.Serializable;

      public class <attr node="/app/parameterMap" name="name"> implements
      Serializable {

      <iterate nodes="/app/parameterMap/parameter"
      name="currentParameter" >

      private <attr node="currentParameter" name="javaType"/> <attr
      node="currentParameter" name="name"/>;

      /**
      * Gets the <attr node="currentParameter" name="name"/>
      * @return Returns a <attr node="currentParameter"
      name="javaType"/>

      */
      public <attr node="currentParameter" name="javaType"/>
      get<attr
      node="currentParameter" name="name" format="U1"/&gt />
      () {
      return <attr node="currentParameter" name="name"/>;
      }
      /**
      * Sets the <attr node="currentParameter" name="name"/>
      * @param <attr node="currentParameter" name="javaType"/> The
      <attr node="currentParameter" name="name"/> to set
      */
      public void set<attr node="currentParameter" name="name"
      format="U1"/&gt />
      (<attr node="currentParameter" name="javaType"/>
      <attr node="currentParameter" name="name"/>) {
      this.<attr node="currentParameter" name="name"/>
      = <attr
      node="currentParameter" name="name"/>
      ;
      }



      </iterate>
      }



      图 43. 应用模式



生成第二个 JavaBean

要了解我们的模式的通用性,那么需要通过生成其他的一些内容来对其进行测试。我们的模式刚刚从单个模型生成了单个文件。然而,我们可以进行一些细微 的修改。(另外,您可以从 C:/DPTKArticles/Part1/Part1Solution.zip 加载解决方案项目交换文件,并运行最后的结果。)

  1. 让我们向模型中添加另一个 JavaBean。从 MyJavaBeanProject 中打开 sample.appdef 文件(图 44),然后添加一个附加的 parameterMap 标记,如清单 14 中的粗体文本所示。



    图 44. 打开 sample.appdef 文件




    清单 14
    <app>
    <parameterMap class="com.ibm.dptk.ibatis.dataobject.Customer"
    id="newCustomerMap" >
    <parameter property="customerId" javaType="java.lang.Integer"/>
    <parameter property="name" javaType="java.lang.String"/>
    <parameter property="address1" javaType="java.lang.String" />
    <parameter property="address2" javaType="java.lang.String" />
    <parameter property="city" javaType="java.lang.String" />
    <parameter property="state" javaType="java.lang.String" />
    <parameter property="zip" javaType="java.lang.String" />
    </parameterMap>
    <parameterMap class="com.ibm.dptk.ibatis.dataobject.Order"
    id="newCustomerMap" >
    <parameter property="customerId" javaType="java.lang.Integer"/>
    <parameter property="orderId" javaType="java.lang.String" />
    </parameterMap>
    </app>

  2. 接下来,要对该模式进行更新,以使它能够生成多个文件,我们需要对 control.pat 文件进行更新:

    1. 打开 the control.pat 文件,并按照下面粗体文本的内容进行修改。我们可以使用 iterate 标记批量地生成文件,以及批量地更新模型。



      清单 15
      *** High-Level Controller

      *** Apply naming conventions

      <include template="ibatis.java.bean.generator/controller/naming.pat"/>


      *** Derive names and other data

      <include template="ibatis.java.bean.generator/controller/derived.pat"/>

      <iterate nodes="/app/parameterMap" name="currentBean" >
      <setAttr node="currentBean"
      name="classname" ><attr
      node="currentBean"
      name="class"></setAttr>
      <setAttr node="currentBean"
      name="name" ><attr
      node="currentBean" name="class"
      format="QC"></setAttr>
      <setAttr node="currentBean"
      name="dir"><attr
      node="currentBean" name="class"
      format="PD"></setAttr>
      <setAttr node="currentBean"
      name="package"><attr
      node="currentBean" name="class"
      format="QP" /></setAttr>
      </iterate>



      *** Dump the modified appdef file for testing and debug purposes


      <start template="ibatis.java.bean.generator/view/dump.pat" resource="dump.xml"
      project="MyJavaBeanProject" replace="true"/>

      <iterate nodes="/app/parameterMap" name="currentBean" >
      <start template="ibatis.java.bean.generator/view/JavaBean.pat"
      resource="%currentBean(dir)%.java" replace="true"/>
      </iterate>


      package <attr node="currentBean" name="package" />;

      import java.io.Serializable;

      public class <attr node="currentBean" name="name"> implements Serializable {

      <iterate nodes="currentBean/parameter" name="currentParameter" >

      private <attr node="currentParameter" name="javaType"/> <attr
      node="currentParameter" name="property"/>;

      /**
      * Gets the <attr node="currentParameter" name="property"/>
      * @return Returns a <attr node="currentParameter" name="javaType"/>
      */
      public <attr node="currentParameter" name="javaType"/> get<attr
      node="currentParameter" name="property" format="U1"/&gt />() {
      return <attr node="currentParameter" name="property"/>;
      }
      /**
      * Sets the <attr node="currentParameter" name="property"/>
      * @param <attr node="currentParameter" name="javaType"/> The <attr
      node="currentParameter" name="property"/> to set
      */
      public void set<attr node="currentParameter" name="property"
      format="U1"/&gt />
      (<attr node="currentParameter" name="javaType"/> <
      attr node="currentParameter" name="property"/>) {
      this.<attr node="currentParameter" name="property"/>
      = <attr node="currentParameter" name="property"/>;
      }

      </iterate>
      }

结束语

在 本文中,我们通过一个简单的示例向您介绍了如何使用 DPTK。然而,DPTK 还可以用来以最少的工作量解决非常复杂的问题。我们重点关注于构建模式模板;DPTK 还提供了相应的分析工具,用于从现有的实现中发现模型。这使得我们可以通过反向工程将代码转换到相应的中性模型和功能,它们可以作为构建基于资产的业务的 基础。在后续文章中,将介绍一些更复杂的问题,以及如何使用设计模式工具箱中更高级的特性来解决这些问题。


致谢

本文作者要感谢 Geoffrey Hambrick 为本文提供了有价值的建议和评论。

下载

描述 名字 大小 下载方法
Code samples DPTKArticleMaterials.zip 11 KB  FTP|HTTP
关于下载方法的信息


参考资料



作者简介

 

Roland Barcia 是位于纽约/新泽西地区的 IBM WebSphere 软件服务部的一位认证 IT 专家。他是 IBM WebSphere: Deployment and Advanced Configuration 的合著者。有关 Roland 的详细信息,请访问他的网站


 

Chris Gerken 是 IBM Software Services for WebSphere group 中 Asset Reuse Enablement Team 的成员。他创建和编写了设计模式工具箱。

 

你可能感兴趣的:(design pattern)