`
ericFang
  • 浏览: 101521 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

J2ee 模式 Design Patten

    博客分类:
  • J2EE
阅读更多
什么是Design Patten?
  
  简单来说,Design Patten 就是一个常用的方案。 在我们的开发过程中,经常会遇到一些相同或者相近的问题,每次我们都会去寻找一个新的解决方法,为了节省时间提高效率,我们提供一些能够解决这些常见问题的,被证实可行的方案,构成一个统一的资源库。

  一个Design Patten描述了一个被证实可行的方案。这些方案非常普通,是有完整定义的最常用的模式。 这些模式可以被重用,有良好的伸缩性,而这些Design Patten的优势将在设计J2EE应用时得到体现。

  1. Model-View-Controller

  a. 问题

  如果开发一个企业级应用,只需要一种客户端的话,那么一切都非常容易解决。但真实情况是,我们必须面对运行在各种设备上客户端,象PDA,WAP浏览器以及运行在桌面上的浏览器,我们不得不开发不同的应用程序来处理来自不同客户端的请求。数据访问与现实将混淆在一起,可能会出现重复的数据访问,导致整个开发周期没有必要的延长。

  b. 建议的解决方法

  Model-View-Controller (MVC) 开发模式被证明是有效的处理方法之一。它可以分离数据访问和数据表现。你可以开发一个有伸缩性的,便于扩展的控制器,来维护整个流程。如图1所示为整个模式的结构。MVC模式可以被映射到多层企业级的J2EE应用上。

  § 所有的企业数据以及商业逻辑可以作为模式。

  § 视图可以通过模式访问数据,并根据客户端的要求来显示数据。视图必须保证当模式改变的时候,数据显示也必须同时改变。

  § 控制器用来结合模式和视图,把客户端来的请求转换成模式能够理解并执行的请求,并且根据请求以及执行结果来决定下一次显示那一个视图。

  根据以上的逻辑,你可以象这样建立一个应用:

  § 应用的商业逻辑由MVC中的模式也就是EJB来表现。模式必须处理由控制器传递过来的对数据的访问请求。

  § 多个页面组成了MVC中的视图,这些视图必须随模式一起更新。

  § 控制器是一系列接收用户动作的对象,他们把用户的请求转换成模式可理解的请求,并决定显示那一个页面当模式处理完请求后。

  c. 要点

  § MVC结构适用于那些多用户的,可扩展的,可维护的,具有很高交互性的系统。

  § MVC可以很好的表达用户的交互和系统模式。

  § 很方便的用多个视图来显示多套数据,是系统很方便的支持其他新的客户端类型。

  § 代码重复达到最低。

  § 由于分离了模式中的流控制和数据表现,可以分清开发者的责任,另外,也可以加快产品推向市场的时间。

2. Front Controller

  a. 问题

  MVC给出了一个整个应用的松散的耦合架构。现在来看一下这样一个经常发生的情况。在某一个应用中,用户看到的视图和他所做的操作密切相关。这是一些具有高度交互性的页面,而这些页面之间含有高度的依赖性。在没有任何模式的时候,这个应用只是一个许多独立的页面的集合,维护和扩展变得异常困难。

  § 当一个页面移动后,其他含有这个页面链接的文件,都必须修改。

  § 当有一系列页面需要口令保护时,许多配置文件需要修改,或者页面需要包含新的标记。

  § 当一个页面需要一个新的表示层时,页面中的标记要被重新安排。

  当这个系统变得复杂时,这些问题将变得更糟。如果用MVC来解决的话,就变成一个如何管理控制器和视图之间交互的问题。

  b. 建议的解决方法

  前台控制模式可以解决这个问题。这个模式中,所有的请求都被传送到一个对象中。这个主要的对象将处理所有的请求,决定以后显示那一个视图,以及实现必要的安全需求。对于把视图显示以及其他功能实现集中到一个主要的对象中,将使修改变得很容易,对应用的修改,可以在所有视图中反映出来。

  c. 要点

  § 这个模式对于需要在多个含有动态数据的页面之间进行复杂导航的系统来说,是很有效的。

  § 这个模式对于要在所有页面中都包含模板,转换等的应用来说,也是很有效的。

  § 由于视图的选择集中在前端控制器上,因此,视图的导航变得更加容易理解和便于配置。

  § 视图重用和变更会更加容易。

  § 视图之间的复杂交互,使得控制器变得复杂。从而,当应用发展的时候,控制器将变得难以维护。不过,大部分情况下可以用XML映射来解决。

  § 实现应用要求的安全性检验变得很简单。

  § 这个模式不适合小型的,只显示静态内容的应用。

  d. 样例

  § RequestMappings.xml 文件映射了传入的请求,处理器以及下一个页面。

useRequestHandler="true"
requiresSecurityCheck="true" nextScreen="screen2.jsp">



com.blah1.blah2.blah3.request1Handler


  以上这个文件是控制器的指定配置,控制器的代码如下:

  § FrontControllerImpl.java 利用上面的XML实现了控制器

// all required imports
// exceptions to be caught appropriately wherever applicable

public class FrontControllerImpl extends HttpServlet {

// all required declarations, definitions
private HashMap requestMappings;

public void init() {
// load the mappings from XML file into the hashmap
}

public void doPost(HttpServletRequest request,

HttpServletResponse response)
throws IOException, ServletException

{
doGet(request, response);
}

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String currentPage= request.getPathInfo();
// get all mapping info for "currentPage" from the hashmap
// if "securityCheckRequired = true", do the security check
// if "useRequestHandler = true", pass on the incoming request to the specified handler
// forward the results to the given "nextScreen"
}

  用这种方法实现的控制器将很容易维护,当应用有新的变动的时候,只要修改XML文件就能解决了。前台控制模式将使在视图和控制器之前有复杂交互的J2EE应用变得简单。


3. Session Fa?ade

  a. 问题

  前台控制给出了一个基于MVC的,能有效管理用户与J2EE应用之间进行的复杂交互。这个模式可以使处理页面的现实顺序和用户的并发请求变得简单。并且使增加和改变页面现实变得更加容易。

  另外一个常见的问题是,当EJB或者业务逻辑发生变化的时候,应用的客户端也必须随之改变。我们来看一下这个问题。

  一般来说,为了表现一个账户中的用户,我们使用一个业务逻辑来表示账户中的信息,象用户名和口令,再用一个EJB来管理用户的个人信息,象爱好,语言等。当要创建一个新的账号或者修改一个已经存在的账号时,必须访问包含账号信息的EJB,读取个人信息,修改并且保存,这样的一个流程。

  当然,这只是一个非常简单的例子,实际情况可能比这个复杂的多,象查看用户定制了哪些服务,检验客户信用卡的有效性,存放订单等。在这个案例中,为了实现一个完整的流程,客户端必须访问账户EJB来完成一系列适当的工作。下面的例子显示了一个Servlet客户端如何来控制一个用户订单。

  A servlet that does the workflow required for placing an order

// all required imports;
// exceptions to be caught appropriately wherever applicable;
// This servlet assumes that for placing an order the account and
// credit status of the customer has to be checked before getting the
// approval and committing the order. For simplicity, the EJBs that
// represent the business logic of account, credit status etc are
// not listed

public class OrderHandlingServlet extends HttpServlet {

// all required declarations, definitions

public void init() {
// all inits required done here
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// other logic as required
// Get reference to the required EJBs
InitialContext ctxt = new InitialContext();
Object obj = ctxt.lookup("java:comp/env/ejb/UserAccount");
UserAccountHome acctHome = (UserAccountHome)
PortableRemoteObject.narrow(obj, UserAccountHome.class);
UserAccount acct = acctHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CreditCheck");
CreditCheckHome creditCheckHome = (CreditCheckHome)
PortableRemoteObject.narrow(obj, CreditCheckHome.class);
CreditCheck credit = creditCheckHome.create();
obj = ctxt.lookup("java:comp/env/ejb/Approvals");
ApprovalsHome apprHome = (ApprovalsHome)
PortableRemoteObject.narrow(obj, ApprovalsHome.class);
Approvals appr = apprHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CommitOrder");
CommitOrderHome orderHome = (CommitOrderHome)
PortableRemoteObject.narrow(obj, CommitOrderHome.class);
CommitOrder order = orderHome.create();

// Acquire the customer ID and order details;
// Now do the required workflow to place the order
int result = acct.checkStatus(customerId);
if(result != OK) {
// stop further steps
}
result = credit.checkCreditWorth(customerId, currentOrder);
if(result != OK) {
// stop further steps
}
result = appr.getApprovals(customerId, currentOrder);
if(result != OK) {
// stop further steps
}

// Everything OK; place the order
result = order.placeOrder(customerId, currentOrder);

// do further processing as required
}


  以上的代码显示了一个单个的客户端。如果这个应用支持多种客户端的话,必须为每一个客户端制定一种处理方法来完成工作流程。如果有一个EJB的实现流程需要改变的话,那么所有的参与这个流程的客户端都需要改变。如果不同的EJB之间的交互需要改变的话,所有的客户端都必须知道这一点,如果流程中需要增加一个新的步骤的话,所有的客户端也必须随之修改。

  这样一来,EJB和客户端之间的改变变得非常困难。客户端必须对每个EJB分开进行访问,致使网络速度变慢。同样,应用越复杂,麻烦越大。
b. 建议的解决方法

  解决这个问题的方法是,把客户端和他们使用的EJB分割开。建议适用Session Fa?ade模式。这个模式通过一个Session Bean,为一系列的EJB提供统一的接口来实现流程。事实上,当客户端只是使用这个接口来触发流程。这样,所有关于EJB实现流程所需要的改变,都和客户端无关。

  看下面这个例子。这段代码用来控制与客户相关的订单的处理方法。

// All imports required
// Exception handling not shown in the sample code

public class OrderSessionFacade implements SessionBean {

// all EJB specific methods like ejbCreate defined here
// Here is the business method that does the workflow
// required when a customer places a new order

public int placeOrder(String customerId, Details orderDetails)
throws RemoteException {
// Get reference to the required EJBs
InitialContext ctxt = new InitialContext();
Object obj = ctxt.lookup("java:comp/env/ejb/UserAccount");
UserAccountHome acctHome = (UserAccountHome)
PortableRemoteObject.narrow(obj, UserAccountHome.class);
UserAccount acct = acctHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CreditCheck");
CreditCheckHome creditCheckHome = (CreditCheckHome)
PortableRemoteObject.narrow(obj, CreditCheckHome.class);
CreditCheck credit = creditCheckHome.create();
obj = ctxt.lookup("java:comp/env/ejb/Approvals");
ApprovalsHome apprHome = (ApprovalsHome)
PortableRemoteObject.narrow(obj, ApprovalsHome.class);
Approvals appr = apprHome.create();
obj = ctxt.lookup("java:comp/env/ejb/CommitOrder");
CommitOrderHome orderHome = (CommitOrderHome)
PortableRemoteObject.narrow(obj, CommitOrderHome.class);
CommitOrder order = orderHome.create();

// Now do the required workflow to place the order
int result = acct.checkStatus(customerId);
if(result != OK) {
// stop further steps
}
result = credit.checkCreditWorth(customerId, currentOrder);
if(result != OK) {
// stop further steps
}
result = appr.getApprovals(customerId, currentOrder);
if(result != OK) {
// stop further steps
}

// Everything OK; place the order
int orderId = order.placeOrder(customerId, currentOrder);

// Do other processing required

return(orderId);
}

// Implement other workflows for other order related functionalities (like
// updating an existing order, canceling an existing order etc.) in a
// similar way


  在模式允许的情况下,Servlet代码将很容易实现。

// all required imports
// exceptions to be caught appropriately wherever applicable

public class OrderHandlingServlet extends HttpServlet {

// all required declarations, definitions

public void init() {
// all inits required done here
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// other logic as required
// Get reference to the session facade
InitialContext ctxt = new InitialContext();
Object obj = ctxt.lookup("java:comp/env/ejb/OrderSessionFacade");
OrderSessionFacadeHome facadeHome = (OrderSessionFacadeHome)
PortableRemoteObject.narrow(obj, OrderSessionFacadeHome.class);
OrderSessionFacade facade = facadeHome.create();

// trigger the order workflow
int orderId = facade.placeOrder(customerId, currentOrder);

// do further processing as required
}


  就象上面显示的,客户端的逻辑变得非常简单。流程中的任何改变只要修改模式中的一处地方就可以了。客户端可以仍旧使用原来的接口,而不必做任何修改。同样,这个模式可以用来响应其他处理器的流程处理。这让你能用同样的模式来处理不同客户端的不同流程。在这个例子中,模式提供了很好的伸缩性和可维护性。
c. 要点

  § 既然这种模式不涉及到数据访问,就应该用Session Bean来实现。

  § 对于用简单接口来实现复杂EJB的子系统来说,是一个理想的选择。

  § 这个模式不适用于无流程处理的应用。

  § 这个模式可以减少客户端于EJB之间的通信和依赖。

  § 所有和EJB有关的交互,都有同一个Session Bean来控制,可以减少客户端对EJB的误用。

  § 这个模式可以使支持多类型客户端变得更容易。

  § 可以减少网络数据传递。

  § 所有的服务器端的实现细节都对客户端隐藏,在改变发生后,客户端不用重新发布。

  § 这个模式可以同样看成一个集中处理器来处理所有的安全或日志纪录。

  4. Data Access Object

  a. 问题

  目前为止,你看到的模型都是用来构建可伸缩的,易于维护的J2EE应用。这些模式尽可能的把应用在多个层上来实现。但是,还有一点必须强调:EJB的数据表现。它们包括象EJB这样的数据库语言。如果数据库有改变的话,相应的SQL也必须改变,而EJB也必须随之更新。

  这些常见问题就是:访问数据源的代码与EJB结合在一起,这样致使代码很难维护。看以下的代码。

  An EJB that has SQL code embedded in it

// all imports required
// exceptions not handled in the sample code

public class UserAccountEJB implements EntityBean {

// All EJB methods like ejbCreate, ejbRemove go here
// Business methods start here

public UserDetails getUserDetails(String userId) {

// A simple query for this example
String query = "SELECT id, name, phone FROM userdetails WHERE name = " + userId;

InitialContext ic = new InitialContext();
datasource = (DataSource)ic.lookup("java:comp/env/jdbc/DataSource");
Connection dbConnection = datasource.getConnection();
Statement stmt = dbConnection.createStatement();
ResultSet result = stmt.executeQuery(queryStr);

// other processing like creation of UserDetails object

result.close();
stmt.close();
dbConnection.close();
return(details);
}
}


  b. 建议的解决方法

  为了解决这个问题,从而让你能很方便的修改你的数据访问。建议使用DAO模式。这个模式把数据访问逻辑从EJB中拿出来放入独立的接口中。结果是EJB保留自己的业务逻辑方法,在需要数据的时候,通过DAO来访问数据库。这样的模式,在要求修改数据访问的时候,只要更新DAO的对象就可以了。看以下的代码。

  A Data Access Object that encapsulates all data resource access code

// All required imports
// Exception handling code not listed below for simplicity

public class UserAccountDAO {

private transient Connection dbConnection = null;

public UserAccountDAO() {}

public UserDetails getUserDetails(String userId) {

// A simple query for this example
String query = "SELECT id, name, phone FROM userdetails WHERE name = " + userId;

InitialContext ic = new InitialContext();
datasource = (DataSource)ic.lookup("java:comp/env/jdbc/DataSource");
Connection dbConnection = datasource.getConnection();
Statement stmt = dbConnection.createStatement();
ResultSet result = stmt.executeQuery(queryStr);

// other processing like creation of UserDetails object

result.close();
stmt.close();
dbConnection.close();
return(details);
}

// Other data access / modification methods pertaining to the UserAccountEJB
}


  现在你有了一个DAO对象,利用这个对象你可以访问数据。再看以下的代码。

  An EJB that uses a DAO

// all imports required
// exceptions not handled in the sample code

public class UserAccountEJB implements EntityBean {

// All EJB methods like ejbCreate, ejbRemove go here

// Business methods start here

public UserDetails getUserDetails(String userId) {

// other processing as required
UserAccountDAO dao = new UserAccountDAO();
UserDetails details = dao.getUserDetails(userId);
// other processing as required
return(details);
}
}



  任何数据源的修改只要更新DAO就可以解决了。另外,为了支持应用能够支持多个不同的数据源类型,你可以开发多个DAO来实现,并在EJB的发布环境中指定这些数据源类型。在一般情况下,EJB可以通过一个Factory对象来得到DAO。用这种方法实现的应用,可以很容易的改变它的数据源类型。

  c. 要点

  § 这个模式分离了业务逻辑和数据访问逻辑。

  § 这种模式特别适用于BMP。过一段时间,这种方式同样可以移植到CMP中。

  § DAOs可以在发布的时候选择数据源类型。

  § DAOs增强了应用的可伸缩性,因为数据源改变变得很容易。

  § DAOs对数据访问没有任何限制,甚至可以访问XML数据。

  § 使用这个模式将导致增加一些额外的对象,并在一定程度上增加应用的复杂性。
分享到:
评论

相关推荐

    J2EE_Design_Patterns.rar

    J2EE_Design_Patterns.rar

    J2ee Design Pattern

    Crawford and Kaplan's J2EE Design Patterns approaches the subject in a unique, highly practical and pragmatic way. Rather than simply present another catalog of design patterns, the authors broaden ...

    Core j2ee Patterns Best Practices And Design Strategies

    标题《Core J2EE Patterns Best Practices And Design Strategies》和描述部分介绍了软件设计模式的重要性,将设计模式比喻为一个组织的“部落记忆”的有形体现。设计模式是解决常见问题的通用解决方案,它源自之前...

    设计模式(design pattern)

    通过8个系统,指出了一个成熟Java/J2EE系统设计开发的正确之道:Model(建模)、Patterns(模式)和Framework(框架)

    J2EE design pattern generator-开源

    **J2EE设计模式生成器** 是一个专为Eclipse集成开发环境设计的开源插件,它的主要功能是自动生成J2EE设计模式相关的代码,极大地简化了开发过程中的模式应用。这个工具不仅提供了基本的代码生成服务,还支持对J2EE...

    design-pattern(设计模式,包括创建型、结构型、行为型三大类共23种常见的设计模式和J2EE常见设计模式等).zip

    本压缩包"design-pattern(设计模式,包括创建型、结构型、行为型三大类共23种常见的设计模式和J2EE常见设计模式等).zip"提供了全面的设计模式学习资源,适用于初学者和有经验的开发者,帮助他们提升软件设计能力。...

    expert one on one j2ee design

    本书《Expert One-on-One J2EE Design and Development》由Spring框架的创始人Rod Johnson撰写,是深入探讨Java 2 Platform, Enterprise Edition(J2EE)架构及设计模式的经典之作。本书不仅对J2EE平台进行了全面的...

    Core J2EE Patterns - Best Practices and Design Strategies - 2nd Edition

    ### Core J2EE Patterns: Best Practices and Design Strategies — 第二版 #### 书籍概述 《Core J2EE Patterns: Best Practices and Design Strategies》第二版是一本面向Java 2 Platform, Enterprise Edition ...

    设计模式精解-GoF 23种设计模式精解JAVA版 PDF

    著名的EJB领域顶尖的专家Richard Monson-Haefel在其个人网站:www.EJBNow.com中极力推荐的GoF的《设计模式》,原文如下: Design ...就Java语言体系来说,GOF的设计模式是Java基础知识和J2EE框架知识之间一座隐性的"桥"。

    designpattern:设计模式

    designpattern 设计模式 觉得看总结太单调,fork下来看看代码吧。 前情提要——简单工厂 简单工厂不是一个标准设计模式。 让客户端只知道接口、不知道具体实现,而设计工厂方法来生成具体实现的实例。把new Impl()放...

    设计模式_java

    4. 建造者模式(Builder Design Pattern):建造者模式属于创建型模式,它提供了一种创建复杂对象的方法。该模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式适用于那些...

    designpattern:Java设计模式

    设计模式分为4种类型:创建型,结构型,行为型和J2EE 创作模式 结构模式 行为模式 责任链 命令 口译员 迭代器 调解员 纪念 观察者 状态 空对象 战略 模板 威斯特 J2EE模式 商务代表 复合实体 道 前置控制器 拦截...

    java设计模式四大常用架构迭代模型并行排序算法.pdf

    1995 年,著名的书籍《Design Pattern》出版,总结了 23 种经典的设计模式,成为软件设计的开创性著作。Java 语言作为面向对象编程语言的优秀代表,非常适合设计模式的实施。 Java 中的设计模式主要体现在 J2SE、...

    二十三种设计模式【PDF版】

    2.设计模式是比 J2EE 等框架软件更小的体系结构,J2EE 中许多具体程序都是应用设计模式来完成的,当你深入到 J2EE 的内 部代码研究时,这点尤其明显,因此,如果你不具备设计模式的基础知识(GoF 的设计模式),你很难...

    core j2ee patterns [3 parts] - part1

    prentice hall - core j2ee patterns - best practices and design strategies, second edition.part1

    Core J2EE™ Patterns: Best Practices and Design Strategies, Second Edition

    By Deepak Alur, John Crupi, Dan Malks Publisher : Prentice Hall PTR Pub Date : June 10, 2003 ISBN : 0-13-142246-4 Pages : 650

    EJB系统开发实战录之三

    ### EJB系统开发实战录之三:深入理解Value Object Design Pattern及其应用 #### 一、引言 在《EJB系统开发实战录之三》这篇文章中,作者李维和庄永璋介绍了如何在EJB(Enterprise JavaBeans)系统中使用Value ...

    java设计模式_四大常用架构_迭代模型_并行排序算法

    1995年,由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位作者合著的《Design Pattern》(中文译名:《设计模式》)出版,标志着面向对象编程中模式化方法的开创性成果。这本书总结了软件实践中常见...

    简单工厂,单例源码

    结合J2EE7_DesignPattern这个文件名,我们可以推测这可能是一个关于J2EE 7版本中的设计模式实践项目,包含了这两个模式的实际应用案例。通过分析和学习这些源码,你可以更好地理解如何在实际项目中应用简单工厂和...

Global site tag (gtag.js) - Google Analytics