模式與框架-Java EE設計與開發(fā).doc_第1頁
模式與框架-Java EE設計與開發(fā).doc_第2頁
模式與框架-Java EE設計與開發(fā).doc_第3頁
模式與框架-Java EE設計與開發(fā).doc_第4頁
模式與框架-Java EE設計與開發(fā).doc_第5頁
已閱讀5頁,還剩73頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第1頁,共78頁 模式與框架模式與框架 javajava eeee設計與開發(fā)設計與開發(fā) 第2頁,共78頁 目錄 第第1章章 模式與框架介模式與框架介紹紹2 1.1 什么是模式. 2 1.2 什么是框架. 3 1.3 模式與框架的區(qū)別.3 1.4 架構模式. 3 1.5 java ee核心模式.4 1.6 gof模式. 6 第第2章章 數據數據層層框架與模式框架與模式7 2.1 示例. 7 2.2 使用模式. 9 2.3 使用設計原則.16 2.4 數據層框架.21 2.5 調用. 29 第第3章章 業(yè)務層業(yè)務層框架與模式框架與模式30 第第4章章 表表現(xiàn)層現(xiàn)層框架與模式框架與模式30 第第5章章 mvc框架與框架與應應用用31 第3頁,共78頁 第第1章章 模式與框架介紹模式與框架介紹 1.1 1.1 什么是模式什么是模式 模式就是解決問題的方法論。每一種模式都描述了解決某一類問題的最佳方法,至少 到目前為止是。模式是理論與實踐相結合而總結出來的最有效的解決方案,它將隨著技 術的發(fā)展而不斷創(chuàng)新,不斷完善,所以舊的模式會發(fā)現(xiàn)不再適用,而新的模式會出現(xiàn)。 模式在各個應用領域都有,譬如在建筑設計中,模式最為常見。如將門安裝在距離墻 角落 120 公分處,窗戶與欄桿的高度在 90 公分左右,長高寬為 300 的模數等。同理,軟 件設計中,模式也是層出不窮,大量的架構模式,創(chuàng)建模式,結構模式,行為模式,表 現(xiàn)層模式,業(yè)務層模式,數據層模式等等。 1.2 1.2 什么是框架什么是框架 就是一組組件、類或接口構成的半成品,僅完成了某些基本功能,譬如日志,安全性, 數據訪問等,但需要在此基礎上進行業(yè)務開發(fā),最終構成一個可用的業(yè)務系統(tǒng)?;诳?架的開發(fā)可以節(jié)省大量的精力而致力于系統(tǒng)的業(yè)務邏輯設計。 譬如在建筑領域,屋架、梁柱就是一個典型的框架,是一個半成品。屋架的作用是 承重,但不能遮風擋雨,必須在上面蓋瓦或鋪設覆蓋物,形成屋頂,才能具備完整的功 能;糧柱的其本作用是劃分空間、承受垂直與橫向的壓力,但不具備封閉空間、隔聲的 效果,尚待在柱間砌筑墻體,在梁間鋪設樓板才能居住。 在軟件開發(fā)中,框架僅提供了部分通用的功能,還必須經過業(yè)務的填充,才能形成一 個功能齊全的業(yè)務系統(tǒng)。 1.3 1.3 模式與框架的區(qū)別模式與框架的區(qū)別 從規(guī)模上講,模式專注于微觀層面的分析與設計,而框架著眼于宏觀的構造。 從實現(xiàn)的角度看,模式只是一種解決問題的方法,一個解決方案,而框架卻是一個實 現(xiàn)這種方案的具體的產品,有著實際的功效與作用。 從關系上講,模式是框架的理論基礎,多個模式的實現(xiàn)構成了一個框架??蚣苁悄J?的具體實現(xiàn),一個局部或全局的框架,一般都要用到模式。 既然是框架,本身就表示它是一種好的通用的產品,怎么體現(xiàn)它是好的呢,模式恰好 證明了它是解決某一類問題的最好的解決方案,所以說,沒有用到模式的框架,將不是 一個良好的可用的框架。 1.4 1.4 架構模式架構模式 第4頁,共78頁 專注于體系結構宏觀的組成與創(chuàng)建,而不注重其細節(jié)。譬如建筑設計中常用的體系結 構模式有:低層建筑采用磚混結構,中高層采用梁柱框架結構,高層建筑普遍采用鋼結 構、剪力墻結構、洐架結構。 在軟件應用領域,架構模式也是豐富多用,主要有以下幾種: 層次模式:layers 管道和過濾模式:pipes and filters 代理模式: broker 黑板模式:blackboard 水平-垂直元素模式:horizontal-vertical metadata mvc 模式:主要針對系統(tǒng)或子系統(tǒng)和接口 1.5 1.5 javajava eeee核心模式核心模式 在 java web 應用與企業(yè)應用領域,常用的體系架構是 mvc。而 mvc 正好體現(xiàn)了分 層的思想。各層之間的聯(lián)系與區(qū)別如下 圖: 表示層表示層 業(yè)務層業(yè)務層 model1 model2 mvc2 mvc 數據層數據層 m v c 我們一般將視圖(view)與控制器(controller)叫做表示層,而模型層太籠統(tǒng),在 實際中,我們將模型層分割為業(yè)務層與數據層。其中 v 或 v+m 構成了我們的 model1 架構, v+c+m 構成了 model2 架構,又叫 web mvc 或 mvc2 架構,因為不支持推式。但我們習 慣將其稱為 mvc 體系架構。 sun java center 定義了 15 種設計模式,在core j2ee patterns書中發(fā)表。按照 mvc 的分層,在每一層都提出了幾種模式,這些模式分別組成各層,最后組成一個完整 第5頁,共78頁 的 mvc 框架。 這些模式分為: 表現(xiàn)層模式,又稱 web 層模式,用于 web 層的界面與 servlet 開發(fā); 業(yè)務層模式,又稱應用層模式,用于業(yè)務邏輯的分層與調用; 數據層模式,又稱集成層模式,用于數據訪問 表現(xiàn)層模式表現(xiàn)層模式 intercepting filter(截獲過濾截獲過濾) 對請求和響應進行截獲和過濾,在 servlet2.3 中已實現(xiàn)的 filter 功能就是屬于此模式。 該模式可用于單點登陸,以及登陸過程驗證等等。 front controller(前端控制器前端控制器) servlet 設計的思想主要是用來調度和轉發(fā)。即調用模型層的類來處理請求,然后將 處理后的信息轉發(fā)到響應頁面進行展示,絕不能將業(yè)務邏輯代碼堆砌在 servlet 方法中。 那么如何能體現(xiàn) servlet 的這一功能需求呢,前端控制器模式很好的解決了這個問題,在 一個項目中,只有一個控制器,它是系統(tǒng)的一個入口,由他調用相應的邏輯 bean,完成 相應的處理工作后,更新視圖 view。 view helper(視圖幫助器視圖幫助器) 將表現(xiàn)層和表現(xiàn)層的數據進行分離,將表現(xiàn)層的數據單獨封裝一層,從而可以更加輕 松的在表現(xiàn)層進行處理與傳遞,而與表現(xiàn)層各層低耦合,這就是 view helper 模式。 composite view(復合視圖復合視圖) 頁面層內容繁多,如何更有效的組織與重用?復合視圖模式將一個復雜的頁面拆成多 個可重用的頁面,各頁面在程序調用過程中分別維護和顯示,從而減少了前臺頁面的復 雜性,也更容易進行個性化和定制。 dispatcher view(派遣視圖派遣視圖) 類似于 service to worker 模式,由 front controller 和 view helper 模式組合而成。 front controller 接受請求,不進行任何業(yè)務邏輯處理,立即重定向到請求的服務頁面,由 頁調用模型層代碼進行處理。這個模式在視圖中進行請求處理,缺點是不適合大型的復 雜的應用程序開發(fā),優(yōu)點是頁面快速響應。 service to worker(服務(服務/工人)工人) 與 dispatcher view 模式共同的地方是,也是由 front controller 和 view helper 模式組 合而成,不同的是,front controller 接受請求以后,首先進行任何業(yè)務邏輯處理,根據處 理結果的不同,而定位到相應的響應視圖,適合用于大型的復雜業(yè)務邏輯的應用系統(tǒng)。 業(yè)務層模式業(yè)務層模式 business delegate(業(yè)務代理)(業(yè)務代理) 第6頁,共78頁 如何減少表現(xiàn)層與數據層的耦合問題,業(yè)務代理模式將業(yè)務邏輯做了封裝,同時也將 數據層的接口做了進一步抽象,從而緩存了調用邏輯,減少了調用開銷。 value object(值對象)(值對象) 如何解決表現(xiàn)層與業(yè)務層之間的數據交換,以及層內部的數據交換問題呢?將常用的 數據單獨封裝成一個 javabean,這樣便于傳遞,也便于取值與設置值。與 map 接口不同 的是,vo 更方便對值進行操作。 value object assembler(值對象匯編器)(值對象匯編器) 將不同的值對象組裝成一個更大的值對象,方便在表現(xiàn)層與數據層之間傳遞數據。 session faade 該模式提供了下一層接口的一個抽象視圖,而不是簡單地把下一層的 api 直接包裝起 來。常用在對實體 bean 的訪問中,以及需要開發(fā)分布式業(yè)務時裝封業(yè)務邏輯。 composite entity(復合實體)(復合實體) 用于 ejb1.1 中封裝實體 bean,已過時。 value list handler(數值清單處理器)(數值清單處理器) 值列表處理器模式創(chuàng)建一個對查詢結果集的緩存。調用者向值列表處理器發(fā)出請求, 值列表處理器返回所需的查詢結果。值列表處理器實現(xiàn)了迭代器模式。 service locator(服務定位器)(服務定位器) 封裝對 jndi 服務器的訪問細節(jié),并且對訪問方式提供了一個單一的控制點,利用緩沖, 效率更高。 數據層模式數據層模式 data access object(數據訪問對象)(數據訪問對象) 對數據庫實體的訪問提供了靈活的調用方式,降低了業(yè)務層與數據層之間耦合度。 service activator(服務激活器)(服務激活器) 異步處理同步 ejb 組件。 1.6 1.6 gofgof模式模式 gof 的設計模式-可復用面向對象軟件的基礎一書中講到了 23 種設計模式,可 謂是最流行最有影響的設計模式。gof 不是一個人,而是指四個人。它的原意是 gangs of four,就是“四人幫” ,就是指此書的四個作者:erich gamma,richard helm,ralph johnson,john vlissides。 這些模式分為三大類,創(chuàng)建性、結構性、行為性。 創(chuàng)建性模式創(chuàng)建性模式 abstract factory 第7頁,共78頁 builder factory methohd prototype singleton 結構性模式結構性模式 adapter bridge composite decorater faade flyweight proxy 行為性模式行為性模式 chain of responsibility command interpreter iterator mediator memento observe state stratege template method visitor 第第2章章 數據層框架與模式數據層框架與模式 第8頁,共78頁 有了前面的基礎,我們開始一個實際的應用。 2.1 2.1 示例示例 譬如我們要訪問數據庫,將一張表的所有記錄查詢出來。怎么做?我們習慣是寫一個 javabean,下面是這個 querytable.java 的源碼: package org.plat.db; import java.sql.connection; import java.sql.drivermanager; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; import java.util.arraylist; import java.util.collection; import java.util.hashmap; import java.util.map; public class querytable public collection getall() string driver = “com.mysql.jdbc.driver“; string url = “jdbc:mysql:/localhost:3306/platdb“; connection conn = null; statement stmt = null; resultset rs = null; string sql = “select uid,uname,email from users“; collection coll = new arraylist(); map map = null; try class.forname(driver); conn = drivermanager.getconnection(url,“root“,“); stmt = conn.createstatement(); rs = stmt.executequery(sql); while(rs.next() map = new hashmap(); map.put(“uid“, rs.getstring(1); map.put(“uname“,rs.getstring(2); map.put(“email“, rs.getstring(3); coll.add(map); catch (sqlexception e) e.printstacktrace(); catch (classnotfoundexception e) e.printstacktrace(); 第9頁,共78頁 finally try if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); catch(sqlexception e) return coll; 我們看這個類,首先連接數據庫,然后執(zhí)行查詢,將每一條記錄都封裝到一個 map 中,再將 map 放在集合中,最后返回一個集合對象 。 這樣寫有什么不對勁的地方呢?首先看滿足面向對象設計嗎?我們說對象有三大特 征,繼承、封裝、多態(tài)。滿不滿足封裝呢?將多個不同的行為封裝在一個對象中,讓這 個對象龐大而臃腫,其本身就不滿足對象的概念。 那怎么封裝呢?封裝就是讓具體的對象去做自己該做的事情,而不是大包大攬。很明 顯,上面的 querytable 對象,即做了連接,又做了查詢,還做了返回值的封裝,封裝太 多,對象的概念模糊。我們要改變這種封裝方式。 2.2 2.2 使用模式使用模式 vo 模式模式 value object 模式認為,大量分散的數據不利于傳輸,也不利于對數據進行操縱,必 須封裝為一個對象用來傳值。上面的例子中,users 表的三個字段被封裝在 map 接口中, 雖然不影響使用,但缺點有二,一是沒有體現(xiàn)對象的封裝性,我們不知道 map 中有什么 東西,map 到底代表了哪一種對象;二是 map 不利數據的獲取與設置。基于 vo 模式,我 們添加 org.accp.vo 包,并重新封裝 users 表的這三個字段,類 users 源代碼如下: package org.plat.vo; import java.util.date; public class users private int pk1; private string uid; private string uname; private string pwd; private string email; private date birth; public date getbirth() return birth; 第10頁,共78頁 public void setbirth(date birth) this.birth = birth; public string getemail() return email; public void setemail(string email) this.email = email; public int getpk1() return pk1; public void setpk1(int pk1) this.pk1 = pk1; public string getpwd() return pwd; public void setpwd(string pwd) this.pwd = pwd; public string getuid() return uid; public void setuid(string uid) this.uid = uid; public string getuname() return uname; public void setuname(string uname) this.uname = uname; dao 模式模式 解決了 map 封裝數據的問題之后,我們再看,連接和查詢也不應該是同一個對象所 做的事情,為什么這么說?一是數據對象訪問模式本身說明了數據訪問應該是一個專門 的對象,它抽象了數據層對表的所有訪問接口,專注于對數據表的操作,如增、刪、改 查,而不管任何其它的業(yè)務邏輯,業(yè)務層將通過 dao 去訪問數據層;二是象 querytable 這樣的類會有很多,基本上一張表會有一個這樣的對象,這么多對象將都會有連接數據 第11頁,共78頁 庫的方法,這本身就不滿足對象封裝與繼承的概念。 所以,我們用 dao 模式,再創(chuàng)建一個類,專門處理對 users 表的操作。類 usersdao 是 dao 模式的具體實現(xiàn)。而對于取數據庫的連接,我們再封裝一個類 connector.java, 下面是它們的源代碼。 connector.java 的源代碼: package org.plat.db; import java.sql.connection; import java.sql.drivermanager; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; public class connector public static connection getconnection() string driver = “com.mysql.jdbc.driver“; string url = “jdbc:mysql:/localhost:3306/platdb“; connection conn = null; try class.forname(driver); conn = drivermanager.getconnection(url,“root“,“); catch (sqlexception e) e.printstacktrace(); catch (classnotfoundexception e) e.printstacktrace(); return conn; public static void close(resultset rs ,statement stmt, connection conn) try if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); catch(sqlexception e) usersdao.java的源碼: package org.plat.dao; import java.sql.connection; import java.sql.resultset; 第12頁,共78頁 import java.sql.sqlexception; import java.sql.statement; import java.util.arraylist; import java.util.collection; import org.old.db.connector; import org.old.vo.users; public class usersdao public collection getall() connection conn = null; statement stmt = null; resultset rs = null; string sql = “select uid,uname,email from users“; collection coll = new arraylist(); users u = null; try conn = connector.getconnection(); stmt = conn.createstatement(); rs = stmt.executequery(sql); while(rs.next() u = new users(); u.setuid(rs.getstring(1); u.setuname(rs.getstring(2); u.setemail(rs.getstring(3); coll.add(u); catch (sqlexception e) e.printstacktrace(); finally connector.close(rs,stmt,conn); return coll; singleton模式模式 我們再看 connector.java,用到了許多靜態(tài)的方法,這樣有什么缺點呢?其實 connector 是一個無狀態(tài)的 javabean,雖然其方法是靜態(tài)的,永遠只分配同一塊內存,但 其類本身卻是可以實例化成多個對象的,這沒有從根本上解決問題。 能不能只讓這個類只有一個實例,然后讓這個唯一的實例去訪問它的方法,而不需要 在所有的方法前冠以 static 修飾符呢?答案是 singleton(單例)模式,它從結構上規(guī)定 第13頁,共78頁 了這個類只需要有一個實例,從而避免了多個實例實際共享同一個方法而帶來的資源消 耗,修改后 connecton.java 源碼如下: package org.plat.db; import java.sql.connection; import java.sql.drivermanager; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; public class connector private static connector connector = new connector(); private connector() public static connector getinstance() return connector; public connection getconnection() string driver = “com.mysql.jdbc.driver“; string url = “jdbc:mysql:/localhost:3306/platdb“; connection conn = null; try class.forname(driver); conn = drivermanager.getconnection(url,“root“,“); catch (sqlexception e) e.printstacktrace(); catch (classnotfoundexception e) e.printstacktrace(); return conn; public void close(resultset rs ,statement stmt, connection conn) try if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); catch(sqlexception e) thread-specefic-storage模式模式 上例中的 connecton.java 的 getconnection()方法,當 web 層通過 servlet 來調用時, 第14頁,共78頁 將會暴露多線程的安全問,怎么解決呢?我們可以加上同步關鍵字 synchronized,但卻是 以性能的損失為代 價的。thread-specific storage(線程專門存儲)模式認為,即然共用資 源困難,干脆不用共享,而為共享的資源專門為每個線程創(chuàng)建一個副本。threadlocal 是 thread local variable,為每一個使用該變量的線程都提供一個變量值的副本,而不會和其 它線程的副本沖突。 connecton.java 進一步優(yōu)化后的源代碼如下: package org.plat.db; import java.sql.connection; import java.sql.drivermanager; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; public class connector private static connector connector = new connector(); private connector() public static connector getinstance() return connector; private static final threadlocal connthread = new threadlocal(); public connection getconnection() connection conn = (connection) connthread.get(); if(conn=null) conn = this._getconnection(); connthread.set(conn); return conn; private connection _getconnection() string driver = “com.mysql.jdbc.driver“; string url = “jdbc:mysql:/localhost:3306/platdb“; connection conn = null; try class.forname(driver); conn = drivermanager.getconnection(url,“root“,“); catch (sqlexception e) e.printstacktrace(); 第15頁,共78頁 catch (classnotfoundexception e) e.printstacktrace(); return conn; public void close(resultset rs ,statement stmt, connection conn) try if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); catch(sqlexception e) 事務事務 再看 usersdao.java 的源碼,首先獲取連接,然后取出表中所有的記錄,最后釋放資 源關閉連接。乍一看似乎沒有什么不妥,其實不然。 想象這樣一種情況,如果我們再添加二張表,一張是崗位表 duty,另一張是用戶與崗 位關聯(lián)的中間表 user_duty?,F(xiàn)在要查看用戶表 users 找到張三的記錄,再將其刪除,同時 刪除用戶崗位表 user_duty 中張三的所有崗位。這一系列的操作,其實是一個事務,任何 時候,為了保證數據的一致性,要么全部提交成功,要么全部提交失敗,不允許出現(xiàn)刪 除張三失敗但刪除崗位成功的情況。 再看我們的例子,我們的 usersdao 中的方法都是自己取連接,用完后自己關閉,自 產自銷,根本不能滿足我們的要求,這時候,我們需要將 connection 中的提交方式改為 手動提交,如果成功,提交,否則全部回滾。為了體現(xiàn)面向對象的封裝,我們再創(chuàng)建一 個事務類,transaction.java: package org.plat.db; import java.sql.connection; import java.sql.sqlexception; public class transaction connection con = null; /* * bool為真表明是自動提交,為假則是有事務需手動提交 */ public transaction(boolean bool) 第16頁,共78頁 try con = connector.getinstance().getconnection(); con.setautocommit(bool); catch (sqlexception e) e.printstacktrace(); public connection getconn() throws sqlexception return con; public void commit() if (con != null) try mit(); catch (sqlexception e) e.printstacktrace(); public void rollback() if (con != null) try con.rollback(); catch (sqlexception e) e.printstacktrace(); public void close() if (con != null) try mit(); catch (sqlexception e) e.printstacktrace(); 2.3 2.3 使用設計原則使用設計原則 ioc原則原則 第17頁,共78頁 我們再看 org.plat.usersdao 類,加上事務后,不再擔心數據一致性的問題了,連接的 獲取不再是直接調用 connector 的 getconnection()方法,而必須從事務中得到。這時又出 現(xiàn)問題,怎么獲取事務呢?是自己直接 new 一個事務,然后取連接嗎?很顯然,這還是 沒有解決事務的問題,即還是自己創(chuàng)建事務取連接,然后關閉事務。同時也違反了 ioc(inverse of control,控制反轉原則) ,即不用關心事務是怎么創(chuàng)建的,誰創(chuàng)建的,我 只關心怎么使用事務就行了。而 ioc 有四種方式,此處我們采用 set 方法傳遞事務。修正 后的 usersdao 源代碼如下: package org.plat.dao; import java.sql.connection; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; import java.util.arraylist; import java.util.collection; import org.old.db.connector; import org.old.vo.users; import org.plat.db.transaction; public class usersdao private transaction transaction; public transaction gettransaction() return transaction; public void settransaction(transaction transaction) this.transaction = transaction; public collection getall() connection conn = null; statement stmt = null; resultset rs = null; string sql = “select uid,uname,email from users“; collection coll = new arraylist(); users u = null; try conn = gettransaction().getconn(); stmt = conn.createstatement(); rs = stmt.executequery(sql); 第18頁,共78頁 while(rs.next() u = new users(); u.setuid(rs.getstring(1); u.setuname(rs.getstring(2); u.setemail(rs.getstring(3); coll.add(u); catch (sqlexception e) e.printstacktrace(); finally connector.close(rs,stmt,null); return coll; 里氏代換原則里氏代換原則 再看上面的 usersdao 類,發(fā)現(xiàn)當有許多表時,基本上是每張表都會有一個對應的 dao 類,這樣將在每個 dao 類里面都封裝了一段共同的代碼,即對事務的獲取和設置。用 里氏代換原則可以解決這個問題,即任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。我 們可以將這段共同代碼封裝成一個基類,讓這些 dao 子類去繼承。 根據以上原則,我們再定義一個 parentdao,作為所有 dao 的父類,封裝事務。 parentdao.java package org.plat.dao; import org.plat.db.transaction; public class parentdao private transaction transaction; public transaction gettransaction() return transaction; public void settransaction(transaction transaction) this.transaction = transaction; isp 原則原則 第19頁,共78頁 前面提到,當有多張表時,將會有多個 dao,如此多的 dao,它們都是數據訪問對象, 都有類似的方法,如增、刪、改、查等,能不能抽象出一個共同的接口,便于管理和擴 展呢?答案是顯而易見的。在抽象成接口時,要有哪些方法,這必須滿足 isp(interface- segregation principle,接口隔離原則)應盡可能提供小的單獨的接口,而不是大的總接口。 由 isp 原則,我們再抽象一個接口,idao.java,所有的子類 dao 去實現(xiàn)這個接口。 package org.plat.dao; import java.sql.sqlexception; import java.util.collection; public interface idao /* * 保存信息 */ public boolean save(object vo) throws sqlexception ; /* * 由主鍵或其它字段刪除信息 */ public boolean delete(object vo) throws sqlexception; /* * 由主鍵修改信息 */ public boolean upd(object vo) throws sqlexception; /* * 由主鍵或其它字段查找用戶信息 */ public object find(object vo) throws sqlexception; /* * 查找表中所有記錄信息 */ public collection findall() throws sqlexception ; 多態(tài)多態(tài) 再 看上面的 idao 接口,我們方法中的參數和返回值都定義為 object 對象,因為每張 表都將有一個對應的 vo,所有的 vo 都是繼承 object 對象,于是我們可以用面向對象的特 征之一多態(tài)來解決這個共同的傳值問題,即特殊動態(tài)綁定。 仔細想一想,特殊動態(tài)綁定固然解決了傳值問題,但也暴露一些隱患。其一,任何類 第20頁,共78頁 都是 object 對象,將造成傳值時類型錯誤,編譯器檢查不到的問題,而這個問題本該在 編譯時解決。其二,object 封裝的對象層面太抽象,不能一目了然的看出這個參數的用意, 也失去了面向對象封裝的特性。 基于以上觀點,我們再封裝一個抽象類,讓所有的值對象 vo 都去繼承這個基類。然 后修改 idao 接口,用這個抽象類去傳遞參數。 valueobject.java package org.plat.vo; import java.io.serializable; public abstract class valueobject implements serializable private string memo; public string getmemo() return memo; public void setmemo(string memo) this.memo = memo; ocp原則原則 再看 org.plat.db 包中的 connector 類,它主要的方法是 getconnection() ,從數據庫中 取連接。假設現(xiàn)在需求有了改動,要將 mysql 數據庫改為 sqlserver 數據庫,我們是不是 要改這個方法呢? 當然要改,不改數據庫都連不上了。修改本身固然沒有問題,但是,它顯然違反了面 向對象的一個核心原則ocp(open close principle,開閉原則) ,對擴展開放,對修改關 閉。在前期的設計中,我們應該盡可能的抽象出更多的方法,以便項目的擴展與維護, 而不是一有問題就改原來的類與方法,進行重構。 既然我們現(xiàn)在就能料到日后可能有多個數據庫的問題,這里我們必須要考慮到擴展, 怎么去做,抽象類。抽象類是 ocp 原則的體現(xiàn),我們再定義一個 connector 的抽象類, 將關閉方法提取到這里,connector.java 源代碼如下: package org.plat.db; 第21頁,共78頁 import java.sql.connection; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.statement; public abstract class connector public abstract connection getconnectionfrommysql(); public abstract connection getconnectionfromsqlserver(); public void close(resultset rs, preparedstatement pst, statement st, connection conn) try if(rs!=null) rs.close(); if(pst!=null) pst.close(); if(st!=null) st.close(); if(conn!=null) conn.close(); catch(exception e) 再寫一個子類 connectorimpl 去實現(xiàn) connector,其中的 getconnectionfromsqlserver() 方法可以不實現(xiàn),待日后擴展用。這樣新的需求出現(xiàn),不需要改動原來的類結構,只需 要將方法體補上即可。 2.4 2.4 框架框架初步初步 將上面的源代碼整理,畫出它們的 uml 圖如下: idao (from dao) usersdao (from dao) connector (from db) connectorimpl (from db) -$connector transaction (from db) parentdao (from dao) users (from vo) valueobject (from vo) 從圖上可以看出,userdao 類實現(xiàn)了 idao 接口并繼承了 parentdao,而 parentdao 又 與事務類 transaction 單向關聯(lián)。 usersdao 又調用 connectorimpl,后者與自己自反關聯(lián),并且繼承了抽象類 第22頁,共78頁 connector。他們在調用時通過 valueobject 類來傳遞參數。 users 類繼承了 valueobject,主要用來封裝數據庫表的字段,并傳遞參數。 整理它們的源代碼,得到如下的清單。 清單清單 1:valueobject.java package org.plat.vo; import java.io.serializable; public abstract class valueobject implements serializable private string memo; public string getmemo() return memo; public void setmemo(string memo) this.memo = memo; 清單清單 2:users.java package org.plat.vo; import java.util.date; public class users extends valueobject private int pk1; private string uid; private string uname; private string pwd; private string email; private date birth; public date getbirth() return birth; public void setbirth(date birth) this.birth = birth; public string getemail() return email; public void setemail(string email) 第23頁,共78頁 this.email = email; public int getpk1() return pk1; publi

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論