積累,創(chuàng)造,分享!

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            25 Posts :: 13 Stories :: 26 Comments :: 0 Trackbacks

          什么是Design Patten?

              簡(jiǎn)單來(lái)說(shuō),Design Patten 就是一個(gè)常用的方案。 在我們的開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)遇到一些相同或者相近的問(wèn)題,每次我們都會(huì)去尋找一個(gè)新的解決方法,為了節(jié)省時(shí)間提高效率,我們提供一些能夠解決這些常見(jiàn)問(wèn)題的,被證實(shí)可行的方案,構(gòu)成一個(gè)統(tǒng)一的資源庫(kù)。
              一個(gè)Design Patten描述了一個(gè)被證實(shí)可行的方案。這些方案非常普通,是有完整定義的最常用的模式。 這些模式可以被重用,有良好的伸縮性,而這些Design Patten的優(yōu)勢(shì)將在設(shè)計(jì)J2EE應(yīng)用時(shí)得到體現(xiàn)。

          1. Model-View-Controller

          a. 問(wèn)題
              如果開(kāi)發(fā)一個(gè)企業(yè)級(jí)應(yīng)用,只需要一種客戶(hù)端的話(huà),那么一切都非常容易解決。但真實(shí)情況是,我們必須面對(duì)運(yùn)行在各種設(shè)備上客戶(hù)端,象PDA,WAP瀏覽器以及運(yùn)行在桌面上的瀏覽器,我們不得不開(kāi)發(fā)不同的應(yīng)用程序來(lái)處理來(lái)自不同客戶(hù)端的請(qǐng)求。數(shù)據(jù)訪問(wèn)與現(xiàn)實(shí)將混淆在一起,可能會(huì)出現(xiàn)重復(fù)的數(shù)據(jù)訪問(wèn),導(dǎo)致整個(gè)開(kāi)發(fā)周期沒(méi)有必要的延長(zhǎng)。

          b. 建議的解決方法
              Model-View-Controller (MVC) 開(kāi)發(fā)模式被證明是有效的處理方法之一。它可以分離數(shù)據(jù)訪問(wèn)和數(shù)據(jù)表現(xiàn)。你可以開(kāi)發(fā)一個(gè)有伸縮性的,便于擴(kuò)展的控制器,來(lái)維護(hù)整個(gè)流程。如圖1所示為整個(gè)模式的結(jié)構(gòu)。MVC模式可以被映射到多層企業(yè)級(jí)的J2EE應(yīng)用上。
          § 所有的企業(yè)數(shù)據(jù)以及商業(yè)邏輯可以作為模式。
          § 視圖可以通過(guò)模式訪問(wèn)數(shù)據(jù),并根據(jù)客戶(hù)端的要求來(lái)顯示數(shù)據(jù)。視圖必須保證當(dāng)模式改變的時(shí)候,數(shù)據(jù)顯示也必須同時(shí)改變。
          § 控制器用來(lái)結(jié)合模式和視圖,把客戶(hù)端來(lái)的請(qǐng)求轉(zhuǎn)換成模式能夠理解并執(zhí)行的請(qǐng)求,并且根據(jù)請(qǐng)求以及執(zhí)行結(jié)果來(lái)決定下一次顯示那一個(gè)視圖。
          根據(jù)以上的邏輯,你可以象這樣建立一個(gè)應(yīng)用:
          § 應(yīng)用的商業(yè)邏輯由MVC中的模式也就是EJB來(lái)表現(xiàn)。模式必須處理由控制器傳遞過(guò)來(lái)的對(duì)數(shù)據(jù)的訪問(wèn)請(qǐng)求。
          § 多個(gè)頁(yè)面組成了MVC中的視圖,這些視圖必須隨模式一起更新。
          § 控制器是一系列接收用戶(hù)動(dòng)作的對(duì)象,他們把用戶(hù)的請(qǐng)求轉(zhuǎn)換成模式可理解的請(qǐng)求,并決定顯示那一個(gè)頁(yè)面當(dāng)模式處理完請(qǐng)求后。

          c. 要點(diǎn)
          § MVC結(jié)構(gòu)適用于那些多用戶(hù)的,可擴(kuò)展的,可維護(hù)的,具有很高交互性的系統(tǒng)。
          § MVC可以很好的表達(dá)用戶(hù)的交互和系統(tǒng)模式。
          § 很方便的用多個(gè)視圖來(lái)顯示多套數(shù)據(jù),是系統(tǒng)很方便的支持其他新的客戶(hù)端類(lèi)型。
          § 代碼重復(fù)達(dá)到最低。
          § 由于分離了模式中的流控制和數(shù)據(jù)表現(xiàn),可以分清開(kāi)發(fā)者的責(zé)任,另外,也可以加快產(chǎn)品推向市場(chǎng)的時(shí)間。

          2. Front Controller

          a. 問(wèn)題
              MVC給出了一個(gè)整個(gè)應(yīng)用的松散的耦合架構(gòu)。現(xiàn)在來(lái)看一下這樣一個(gè)經(jīng)常發(fā)生的情況。在某一個(gè)應(yīng)用中,用戶(hù)看到的視圖和他所做的操作密切相關(guān)。這是一些具有高度交互性的頁(yè)面,而這些頁(yè)面之間含有高度的依賴(lài)性。在沒(méi)有任何模式的時(shí)候,這個(gè)應(yīng)用只是一個(gè)許多獨(dú)立的頁(yè)面的集合,維護(hù)和擴(kuò)展變得異常困難。
          § 當(dāng)一個(gè)頁(yè)面移動(dòng)后,其他含有這個(gè)頁(yè)面鏈接的文件,都必須修改。
          § 當(dāng)有一系列頁(yè)面需要口令保護(hù)時(shí),許多配置文件需要修改,或者頁(yè)面需要包含新的標(biāo)記。
          § 當(dāng)一個(gè)頁(yè)面需要一個(gè)新的表示層時(shí),頁(yè)面中的標(biāo)記要被重新安排。
              當(dāng)這個(gè)系統(tǒng)變得復(fù)雜時(shí),這些問(wèn)題將變得更糟。如果用MVC來(lái)解決的話(huà),就變成一個(gè)如何管理控制器和視圖之間交互的問(wèn)題。

          b. 建議的解決方法
              前臺(tái)控制模式可以解決這個(gè)問(wèn)題。這個(gè)模式中,所有的請(qǐng)求都被傳送到一個(gè)對(duì)象中。這個(gè)主要的對(duì)象將處理所有的請(qǐng)求,決定以后顯示那一個(gè)視圖,以及實(shí)現(xiàn)必要的安全需求。對(duì)于把視圖顯示以及其他功能實(shí)現(xiàn)集中到一個(gè)主要的對(duì)象中,將使修改變得很容易,對(duì)應(yīng)用的修改,可以在所有視圖中反映出來(lái)。

          c. 要點(diǎn)
          § 這個(gè)模式對(duì)于需要在多個(gè)含有動(dòng)態(tài)數(shù)據(jù)的頁(yè)面之間進(jìn)行復(fù)雜導(dǎo)航的系統(tǒng)來(lái)說(shuō),是很有效的。
          § 這個(gè)模式對(duì)于要在所有頁(yè)面中都包含模板,轉(zhuǎn)換等的應(yīng)用來(lái)說(shuō),也是很有效的。
          § 由于視圖的選擇集中在前端控制器上,因此,視圖的導(dǎo)航變得更加容易理解和便于配置。
          § 視圖重用和變更會(huì)更加容易。
          § 視圖之間的復(fù)雜交互,使得控制器變得復(fù)雜。從而,當(dāng)應(yīng)用發(fā)展的時(shí)候,控制器將變得難以維護(hù)。不過(guò),大部分情況下可以用XML映射來(lái)解決。
          § 實(shí)現(xiàn)應(yīng)用要求的安全性檢驗(yàn)變得很簡(jiǎn)單。
          § 這個(gè)模式不適合小型的,只顯示靜態(tài)內(nèi)容的應(yīng)用。

          d. 樣例
          § RequestMappings.xml 文件映射了傳入的請(qǐng)求,處理器以及下一個(gè)頁(yè)面

          useRequestHandler="true"
          requiresSecurityCheck="true"
          nextScreen="screen2.jsp">
          com.blah1.blah2.blah3.request1Handler

              以上這個(gè)文件是控制器的指定配置,控制器的代碼如下:
          § FrontControllerImpl.java 利用上面的XML實(shí)現(xiàn)了控制器
          // 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"
          }
          }
              用這種方法實(shí)現(xiàn)的控制器將很容易維護(hù),當(dāng)應(yīng)用有新的變動(dòng)的時(shí)候,只要修改XML文件就能解決了。前臺(tái)控制模式將使在視圖和控制器之前有復(fù)雜交互的J2EE應(yīng)用變得簡(jiǎn)單。


          3. Session Facade

          a. 問(wèn)題
              前臺(tái)控制給出了一個(gè)基于MVC的,能有效管理用戶(hù)與J2EE應(yīng)用之間進(jìn)行的復(fù)雜交互。這個(gè)模式可以使處理頁(yè)面的現(xiàn)實(shí)順序和用戶(hù)的并發(fā)請(qǐng)求變得簡(jiǎn)單。并且使增加和改變頁(yè)面現(xiàn)實(shí)變得更加容易。
          另外一個(gè)常見(jiàn)的問(wèn)題是,當(dāng)EJB或者業(yè)務(wù)邏輯發(fā)生變化的時(shí)候,應(yīng)用的客戶(hù)端也必須隨之改變。我們來(lái)看一下這個(gè)問(wèn)題。
              一般來(lái)說(shuō),為了表現(xiàn)一個(gè)賬戶(hù)中的用戶(hù),我們使用一個(gè)業(yè)務(wù)邏輯來(lái)表示賬戶(hù)中的信息,象用戶(hù)名和口令,再用一個(gè)EJB來(lái)管理用戶(hù)的個(gè)人信息,象愛(ài)好,語(yǔ)言等。當(dāng)要?jiǎng)?chuàng)建一個(gè)新的賬號(hào)或者修改一個(gè)已經(jīng)存在的賬號(hào)時(shí),必須訪問(wèn)包含賬號(hào)信息的EJB,讀取個(gè)人信息,修改并且保存,這樣的一個(gè)流程。
              當(dāng)然,這只是一個(gè)非常簡(jiǎn)單的例子,實(shí)際情況可能比這個(gè)復(fù)雜的多,象查看用戶(hù)定制了哪些服務(wù),檢驗(yàn)客戶(hù)信用卡的有效性,存放訂單等。在這個(gè)案例中,為了實(shí)現(xiàn)一個(gè)完整的流程,客戶(hù)端必須訪問(wèn)賬戶(hù)EJB來(lái)完成一系列適當(dāng)?shù)墓ぷ鳌O旅娴睦语@示了一個(gè)Servlet客戶(hù)端如何來(lái)控制一個(gè)用戶(hù)訂單。
          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
          }
          }
              以上的代碼顯示了一個(gè)單個(gè)的客戶(hù)端。如果這個(gè)應(yīng)用支持多種客戶(hù)端的話(huà),必須為每一個(gè)客戶(hù)端制定一種處理方法來(lái)完成工作流程。如果有一個(gè)EJB的實(shí)現(xiàn)流程需要改變的話(huà),那么所有的參與這個(gè)流程的客戶(hù)端都需要改變。如果不同的EJB之間的交互需要改變的話(huà),所有的客戶(hù)端都必須知道這一點(diǎn),如果流程中需要增加一個(gè)新的步驟的話(huà),所有的客戶(hù)端也必須隨之修改。
              這樣一來(lái),EJB和客戶(hù)端之間的改變變得非常困難。客戶(hù)端必須對(duì)每個(gè)EJB分開(kāi)進(jìn)行訪問(wèn),致使網(wǎng)絡(luò)速度變慢。同樣,應(yīng)用越復(fù)雜,麻煩越大。

          b. 建議的解決方法
              解決這個(gè)問(wèn)題的方法是,把客戶(hù)端和他們使用的EJB分割開(kāi)。建議適用Session Fa?ade模式。這個(gè)模式通過(guò)一個(gè)Session Bean,為一系列的EJB提供統(tǒng)一的接口來(lái)實(shí)現(xiàn)流程。事實(shí)上,當(dāng)客戶(hù)端只是使用這個(gè)接口來(lái)觸發(fā)流程。這樣,所有關(guān)于EJB實(shí)現(xiàn)流程所需要的改變,都和客戶(hù)端無(wú)關(guān)。
              看下面這個(gè)例子。這段代碼用來(lái)控制與客戶(hù)相關(guān)的訂單的處理方法。
          // 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代碼將很容易實(shí)現(xiàn)。
          // 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
          }
          }
              就象上面顯示的,客戶(hù)端的邏輯變得非常簡(jiǎn)單。流程中的任何改變只要修改模式中的一處地方就可以了。客戶(hù)端可以仍舊使用原來(lái)的接口,而不必做任何修改。同樣,這個(gè)模式可以用來(lái)響應(yīng)其他處理器的流程處理。這讓你能用同樣的模式來(lái)處理不同客戶(hù)端的不同流程。在這個(gè)例子中,模式提供了很好的伸縮性和可維護(hù)性。

          c. 要點(diǎn)
          § 既然這種模式不涉及到數(shù)據(jù)訪問(wèn),就應(yīng)該用Session Bean來(lái)實(shí)現(xiàn)。
          § 對(duì)于用簡(jiǎn)單接口來(lái)實(shí)現(xiàn)復(fù)雜EJB的子系統(tǒng)來(lái)說(shuō),是一個(gè)理想的選擇。
          § 這個(gè)模式不適用于無(wú)流程處理的應(yīng)用。
          § 這個(gè)模式可以減少客戶(hù)端于EJB之間的通信和依賴(lài)。
          § 所有和EJB有關(guān)的交互,都有同一個(gè)Session Bean來(lái)控制,可以減少客戶(hù)端對(duì)EJB的誤用。
          § 這個(gè)模式可以使支持多類(lèi)型客戶(hù)端變得更容易。
          § 可以減少網(wǎng)絡(luò)數(shù)據(jù)傳遞。
          § 所有的服務(wù)器端的實(shí)現(xiàn)細(xì)節(jié)都對(duì)客戶(hù)端隱藏,在改變發(fā)生后,客戶(hù)端不用重新發(fā)布。
          § 這個(gè)模式可以同樣看成一個(gè)集中處理器來(lái)處理所有的安全或日志紀(jì)錄。

          4. Data Access Object

          a. 問(wèn)題
              目前為止,你看到的模型都是用來(lái)構(gòu)建可伸縮的,易于維護(hù)的J2EE應(yīng)用。這些模式盡可能的把應(yīng)用在多個(gè)層上來(lái)實(shí)現(xiàn)。但是,還有一點(diǎn)必須強(qiáng)調(diào):EJB的數(shù)據(jù)表現(xiàn)。它們包括象EJB這樣的數(shù)據(jù)庫(kù)語(yǔ)言。如果數(shù)據(jù)庫(kù)有改變的話(huà),相應(yīng)的SQL也必須改變,而EJB也必須隨之更新。
              這些常見(jiàn)問(wèn)題就是:訪問(wèn)數(shù)據(jù)源的代碼與EJB結(jié)合在一起,這樣致使代碼很難維護(hù)。看以下的代碼。
          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. 建議的解決方法
              為了解決這個(gè)問(wèn)題,從而讓你能很方便的修改你的數(shù)據(jù)訪問(wèn)。建議使用DAO模式。這個(gè)模式把數(shù)據(jù)訪問(wèn)邏輯從EJB中拿出來(lái)放入獨(dú)立的接口中。結(jié)果是EJB保留自己的業(yè)務(wù)邏輯方法,在需要數(shù)據(jù)的時(shí)候,通過(guò)DAO來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。這樣的模式,在要求修改數(shù)據(jù)訪問(wèn)的時(shí)候,只要更新DAO的對(duì)象就可以了。看以下的代碼。
          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
          }
              現(xiàn)在你有了一個(gè)DAO對(duì)象,利用這個(gè)對(duì)象你可以訪問(wèn)數(shù)據(jù)。再看以下的代碼。
          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);
          }
          }
              任何數(shù)據(jù)源的修改只要更新DAO就可以解決了。另外,為了支持應(yīng)用能夠支持多個(gè)不同的數(shù)據(jù)源類(lèi)型,你可以開(kāi)發(fā)多個(gè)DAO來(lái)實(shí)現(xiàn),并在EJB的發(fā)布環(huán)境中指定這些數(shù)據(jù)源類(lèi)型。在一般情況下,EJB可以通過(guò)一個(gè)Factory對(duì)象來(lái)得到DAO。用這種方法實(shí)現(xiàn)的應(yīng)用,可以很容易的改變它的數(shù)據(jù)源類(lèi)型。


          c. 要點(diǎn)
          § 這個(gè)模式分離了業(yè)務(wù)邏輯和數(shù)據(jù)訪問(wèn)邏輯。
          § 這種模式特別適用于BMP。過(guò)一段時(shí)間,這種方式同樣可以移植到CMP中。
          § DAOs可以在發(fā)布的時(shí)候選擇數(shù)據(jù)源類(lèi)型。
          § DAOs增強(qiáng)了應(yīng)用的可伸縮性,因?yàn)閿?shù)據(jù)源改變變得很容易。
          § DAOs對(duì)數(shù)據(jù)訪問(wèn)沒(méi)有任何限制,甚至可以訪問(wèn)XML數(shù)據(jù)。
          § 使用這個(gè)模式將導(dǎo)致增加一些額外的對(duì)象,并在一定程度上增加應(yīng)用的復(fù)雜性。

          posted on 2005-08-05 11:35 nighthawk 閱讀(185) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 分析與設(shè)計(jì)
          主站蜘蛛池模板: 萨迦县| 晋中市| 云南省| 昌平区| 西藏| 沾益县| 威信县| 蓝田县| 芮城县| 阿尔山市| 湖州市| 新建县| 金溪县| 浦江县| 中阳县| 白银市| 龙里县| 文昌市| 凌海市| 阿坝| 泸州市| 杨浦区| 鄄城县| 边坝县| 蕲春县| 黔南| 义乌市| 荥阳市| 罗平县| 南汇区| 浦江县| 信丰县| 东阿县| 湘乡市| 瓮安县| 云南省| 郴州市| 遂川县| 抚宁县| 三穗县| 理塘县|