從重構的角度學習bridge設計模式
從重構的角度學習bridge設計模式
Bridge模式是一個在實際系統中經常應用的模式。它最能體現設計模式的原則
針對介面進行程式設計,和使用聚合不使用繼承這兩個原則。
由於我們過分的使用繼承,使類的結構過於複雜,不易理解,難以維護。特別
是在Java中由於不能同時繼承多個類,這樣就會造成多層繼承,維護更難。
Bridge模式是解決多層繼承的根本原因。如果你在實現應用中一個類,需要繼承
兩個以上的類,並且這兩者之間又持有某種關係,它們兩個都會有多種變化。
Bridge模式是把這兩個類,分解為一個抽象,一個實現,使它們兩個分離,這樣
兩種類可以獨立的變化。
抽象就是,把一個實體的共同概念(相同的步驟),抽取出來(分解出幾個相互獨立的步驟),
作為一個過程。如我們把資料庫的 操作抽象為一個過程,有幾個步驟,建立SQL語句,
傳送到資料庫處理,取得結果。
實現就是怎樣完成這個抽象步驟,如傳送到資料庫,需要結合具體的資料庫,考慮怎樣完成這個步驟等。
並且同一步驟可能存在不同的實現,如對不同的資料庫需要不同的實現。
現在我們假設一個情況,也是WEB中經常遇到的,在一個page有輸入框,
如客戶資訊的姓名,地址等,輸入資訊後,然後按查詢按鈕,把查詢的結果顯示出來。
我們現在假設查詢客戶資訊和帳戶資訊,它們在不同的表中。
但是我們的系統面對兩種人群,總部的它們資訊儲存到oracle資料庫,但是各個分公司
的資料儲存在Sybase中,資料庫的位置等各不相同,這兩種的操作不同。
下面是我們一般首先會使用的方式,使用if else進行,判斷,這樣使用系統
難以維護,難以擴充套件,不妨你增加一種查詢,或者一種資料庫試試????
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查詢客戶資訊")){
//如果是查詢客戶資訊,拼SQL語句從客戶表中讀取資料
SQL="select * from Customer "
if(dbType.equal("oracle")){
//從總部資料庫讀取,資料庫為Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分動態從資料庫中取出資料,組裝成Vector,返回
..................................
...................................
}else(dbType.equal("sybase")){
//從分公司資料庫讀取,資料庫為Sybase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分動態從資料庫中取出資料,組裝成Vector,返回
..................................
...................................
}
}else if(ActionType.equal("查詢帳戶資訊")){
//如果是查詢帳戶資訊,拼接SQL語句從帳戶表中讀取資料
SQL="select * from Account "
if(dbType.equal("oracle")){
..........................
..........................
(作者注:此處省略從oracle讀取,約300字)
}else if(dbType.equal("Sybase")){
..........................
..........................
(作者注:此處省略從Sybase讀取,約300字)
}
}
}
}
如果你認為這寫的比較弱智,應該進行使用函式,但是你也會大量使用if else.???
於是我們進行重構,首先我們學習過DAO模式,就是把資料讀取進行分裡,我們定義一個
共同的介面,它負責資料庫的操作,然後根據不同的資料庫進行實現,在我們的查詢操作中,
使用介面,進行操作,這樣就可以不用考慮具體的實現,我們只管實現過程。
查詢共同介面:
public interface searchDB{
public Vector searchFromDB(String SQL)
}
Oracle資料庫的查詢實現
public class searchDBOracleImpl{
public Vector searchFromDB(String SQL){
//從總部資料庫讀取,資料庫為Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
ResultSet rset = stmt.executeQuery (SQL);
.............................
............................
}
}
Sybase資料庫的查詢實現
public class searchDBSysbaseImpl{
public Vector searchFromDB(String SQL){
//從分公司資料庫讀取,資料庫為Sysbase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
ResultSet rset = stmt.executeQuery (SQL);
.............................
............................
}
}
這樣在我們的查詢中就可以使用介面searchDB,但是建立有是一個問題,因為我們不能
靜態的確定,查詢的資料庫型別,必須動態確定,於是我們又想到使用簡單工廠方法,
來分別建立這裡的具體實現,根據類別,建立
public class searchFactory{
public static searchDB createSearch(int DBType){
if(DBType.equal("oracle")){
return searchDBOracleImpl();
}else if(DBType.equal("sybase")){
return searchDBSysbaseImpl();
}
}
}
於是我們的查詢程式碼可以改變為這樣了;
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查詢客戶資訊")){
//如果是查詢客戶資訊,拼SQL語句從客戶表中讀取資料
SQL="select * from Customer "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);
}else if(ActionType.equal("查詢帳戶資訊")){
//如果是查詢帳戶資訊,拼接SQL語句從帳戶表中讀取資料
SQL="select * from Account "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);
}
}
}
是不是簡單一些,如果增加一個新的資料庫,對我們只需增加一個新的資料庫實現便可,
老的程式碼,不需改變,這樣便實現開-閉原則(Open-closed原則),在我們的查詢查詢
中使用的是介面,這就是設計模式的原則,針對介面進行程式設計,並且使用聚合,而不是直接的繼承
大家,可以考慮使用繼承來完成該工作怎樣實現?????
上面是把實現進行分離,實現可以動態變化!!!!!
我們把查詢的操作的具體資料庫實現進行了分離,增強了靈活性,但是我們的查詢。
仍然使用了if else這樣仍然不易進行擴充套件,於是我們進行抽象一個查詢操作的過程,
把它分成幾個具體步驟,建立SQL語句,傳送到資料庫,執行查詢,返回結果。
它們雖然是不同的查詢,SQL各不相同,不同資料庫執行不同,返回結果的內容不同。但是
這個過程卻是不變的,於是我們宣告一個抽象類,來完成這個過程。
public abstract class searchAction{
searchDB obj;
//兩個步驟
public searchDB createSearchImple(int DbType){
return searchFactory.createSearch(DbType);
}
public abstract String createSQL();
//查詢過程,最後返回結果
public vector searchResult(int DbType){
obj=createSearchImple(DbType);
return obj.searchFromDB(createSQL())
}
}
//我們客戶查詢,操作
public class searchCustomerAction{
public String createSQL(){
return "select * from Customer"
}
}
//我們的帳戶查詢操作
public class searchAccountAction{
public String createSQL(){
return "select * from account"
}
}
這樣我們的查詢程式設計簡單的建立SQL語句,我們應該再建立一個工廠方法,
來完成建立它們
public class actionFactory{
public static searchAction ceateAction(int actionType){
if(actionType.equal("customer")){
return searchCustomerAction();
}else if(actionType.equal("account")){
return searchAccountAction();
}
}
}
這樣我們把查詢操作的過程進行了抽象,定義了步驟,和具體過程,經過我們的兩次改變
把抽象部分和實現部分進行分離,使他們都可以獨立的變化,增強靈活性。
我們再看當初查詢實現,現在經過這兩次的地修改,變成了什麼模樣?如下:
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
searchAction action=actionFactory.ceateAction(ActionType);
return action.searchResult(DbType);
}
現在假如增加一個資料庫型別,將會改變那些??,如果增加一種查詢操作需要改變那些???
討論點:
1:在我們的重構過程中,
怎樣使用設計模式原則的???
現在如果增加功能,遵循開閉原則嗎??
2:我們使用了兩個簡單工廠,這是為了簡化,一般最好使用抽象工廠方法,
如果改為抽象工廠,怎樣修改???
我打算寫一系列的文章介紹設計模式,
希望從重構的角度考慮模式的應用,而不是
直接介紹模式,這樣對初學者容易入門,step by step。
如果在自己的程式碼中遇到類似的情景,可以進行重構。
從重構學習proxy,預告
為什麼EJB有Home,remote,bean這三種角色?
為什麼又客戶端與容器進行互動??
介紹在EJB中的應用???
從重構學習decorator??
Bridge模式是一個在實際系統中經常應用的模式。它最能體現設計模式的原則
針對介面進行程式設計,和使用聚合不使用繼承這兩個原則。
由於我們過分的使用繼承,使類的結構過於複雜,不易理解,難以維護。特別
是在Java中由於不能同時繼承多個類,這樣就會造成多層繼承,維護更難。
Bridge模式是解決多層繼承的根本原因。如果你在實現應用中一個類,需要繼承
兩個以上的類,並且這兩者之間又持有某種關係,它們兩個都會有多種變化。
Bridge模式是把這兩個類,分解為一個抽象,一個實現,使它們兩個分離,這樣
兩種類可以獨立的變化。
抽象就是,把一個實體的共同概念(相同的步驟),抽取出來(分解出幾個相互獨立的步驟),
作為一個過程。如我們把資料庫的 操作抽象為一個過程,有幾個步驟,建立SQL語句,
傳送到資料庫處理,取得結果。
實現就是怎樣完成這個抽象步驟,如傳送到資料庫,需要結合具體的資料庫,考慮怎樣完成這個步驟等。
並且同一步驟可能存在不同的實現,如對不同的資料庫需要不同的實現。
現在我們假設一個情況,也是WEB中經常遇到的,在一個page有輸入框,
如客戶資訊的姓名,地址等,輸入資訊後,然後按查詢按鈕,把查詢的結果顯示出來。
我們現在假設查詢客戶資訊和帳戶資訊,它們在不同的表中。
但是我們的系統面對兩種人群,總部的它們資訊儲存到oracle資料庫,但是各個分公司
的資料儲存在Sybase中,資料庫的位置等各不相同,這兩種的操作不同。
下面是我們一般首先會使用的方式,使用if else進行,判斷,這樣使用系統
難以維護,難以擴充套件,不妨你增加一種查詢,或者一種資料庫試試????
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查詢客戶資訊")){
//如果是查詢客戶資訊,拼SQL語句從客戶表中讀取資料
SQL="select * from Customer "
if(dbType.equal("oracle")){
//從總部資料庫讀取,資料庫為Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分動態從資料庫中取出資料,組裝成Vector,返回
..................................
...................................
}else(dbType.equal("sybase")){
//從分公司資料庫讀取,資料庫為Sybase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
Connection conn = DriverManager.getConnection (connect_string);
// Create a statement
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery (SQL);
//以下省略部分動態從資料庫中取出資料,組裝成Vector,返回
..................................
...................................
}
}else if(ActionType.equal("查詢帳戶資訊")){
//如果是查詢帳戶資訊,拼接SQL語句從帳戶表中讀取資料
SQL="select * from Account "
if(dbType.equal("oracle")){
..........................
..........................
(作者注:此處省略從oracle讀取,約300字)
}else if(dbType.equal("Sybase")){
..........................
..........................
(作者注:此處省略從Sybase讀取,約300字)
}
}
}
}
如果你認為這寫的比較弱智,應該進行使用函式,但是你也會大量使用if else.???
於是我們進行重構,首先我們學習過DAO模式,就是把資料讀取進行分裡,我們定義一個
共同的介面,它負責資料庫的操作,然後根據不同的資料庫進行實現,在我們的查詢操作中,
使用介面,進行操作,這樣就可以不用考慮具體的實現,我們只管實現過程。
查詢共同介面:
public interface searchDB{
public Vector searchFromDB(String SQL)
}
Oracle資料庫的查詢實現
public class searchDBOracleImpl{
public Vector searchFromDB(String SQL){
//從總部資料庫讀取,資料庫為Oracle
String connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:HRDB";
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
ResultSet rset = stmt.executeQuery (SQL);
.............................
............................
}
}
Sybase資料庫的查詢實現
public class searchDBSysbaseImpl{
public Vector searchFromDB(String SQL){
//從分公司資料庫讀取,資料庫為Sysbase
String connect_string ="jdbc:sybase:Tds:cai/cai@192.168.1.12:1521:FIN";
DriverManager.registerDriver (new com.sybase.jdbc.SybDriver());
ResultSet rset = stmt.executeQuery (SQL);
.............................
............................
}
}
這樣在我們的查詢中就可以使用介面searchDB,但是建立有是一個問題,因為我們不能
靜態的確定,查詢的資料庫型別,必須動態確定,於是我們又想到使用簡單工廠方法,
來分別建立這裡的具體實現,根據類別,建立
public class searchFactory{
public static searchDB createSearch(int DBType){
if(DBType.equal("oracle")){
return searchDBOracleImpl();
}else if(DBType.equal("sybase")){
return searchDBSysbaseImpl();
}
}
}
於是我們的查詢程式碼可以改變為這樣了;
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
String SQL="";
if(ActionType.equal("查詢客戶資訊")){
//如果是查詢客戶資訊,拼SQL語句從客戶表中讀取資料
SQL="select * from Customer "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);
}else if(ActionType.equal("查詢帳戶資訊")){
//如果是查詢帳戶資訊,拼接SQL語句從帳戶表中讀取資料
SQL="select * from Account "
searchDB obj=searchFactory.createSearch(DbType);
return obj.searchFromDB(SQL);
}
}
}
是不是簡單一些,如果增加一個新的資料庫,對我們只需增加一個新的資料庫實現便可,
老的程式碼,不需改變,這樣便實現開-閉原則(Open-closed原則),在我們的查詢查詢
中使用的是介面,這就是設計模式的原則,針對介面進行程式設計,並且使用聚合,而不是直接的繼承
大家,可以考慮使用繼承來完成該工作怎樣實現?????
上面是把實現進行分離,實現可以動態變化!!!!!
我們把查詢的操作的具體資料庫實現進行了分離,增強了靈活性,但是我們的查詢。
仍然使用了if else這樣仍然不易進行擴充套件,於是我們進行抽象一個查詢操作的過程,
把它分成幾個具體步驟,建立SQL語句,傳送到資料庫,執行查詢,返回結果。
它們雖然是不同的查詢,SQL各不相同,不同資料庫執行不同,返回結果的內容不同。但是
這個過程卻是不變的,於是我們宣告一個抽象類,來完成這個過程。
public abstract class searchAction{
searchDB obj;
//兩個步驟
public searchDB createSearchImple(int DbType){
return searchFactory.createSearch(DbType);
}
public abstract String createSQL();
//查詢過程,最後返回結果
public vector searchResult(int DbType){
obj=createSearchImple(DbType);
return obj.searchFromDB(createSQL())
}
}
//我們客戶查詢,操作
public class searchCustomerAction{
public String createSQL(){
return "select * from Customer"
}
}
//我們的帳戶查詢操作
public class searchAccountAction{
public String createSQL(){
return "select * from account"
}
}
這樣我們的查詢程式設計簡單的建立SQL語句,我們應該再建立一個工廠方法,
來完成建立它們
public class actionFactory{
public static searchAction ceateAction(int actionType){
if(actionType.equal("customer")){
return searchCustomerAction();
}else if(actionType.equal("account")){
return searchAccountAction();
}
}
}
這樣我們把查詢操作的過程進行了抽象,定義了步驟,和具體過程,經過我們的兩次改變
把抽象部分和實現部分進行分離,使他們都可以獨立的變化,增強靈活性。
我們再看當初查詢實現,現在經過這兩次的地修改,變成了什麼模樣?如下:
public class SearchAction(){
public Vector searchData(string ActionType,String DbType){
searchAction action=actionFactory.ceateAction(ActionType);
return action.searchResult(DbType);
}
現在假如增加一個資料庫型別,將會改變那些??,如果增加一種查詢操作需要改變那些???
討論點:
1:在我們的重構過程中,
怎樣使用設計模式原則的???
現在如果增加功能,遵循開閉原則嗎??
2:我們使用了兩個簡單工廠,這是為了簡化,一般最好使用抽象工廠方法,
如果改為抽象工廠,怎樣修改???
我打算寫一系列的文章介紹設計模式,
希望從重構的角度考慮模式的應用,而不是
直接介紹模式,這樣對初學者容易入門,step by step。
如果在自己的程式碼中遇到類似的情景,可以進行重構。
從重構學習proxy,預告
為什麼EJB有Home,remote,bean這三種角色?
為什麼又客戶端與容器進行互動??
介紹在EJB中的應用???
從重構學習decorator??
相關文章
- 從重構的角度學習bridge設計模式 (轉)設計模式
- 從shiro原始碼角度學習建造者設計模式原始碼設計模式
- 從shiro原始碼角度學習工廠方法設計模式原始碼設計模式
- 設計模式----Bridge模式設計模式
- 設計模式--橋接模式Bridge(結構型)設計模式橋接
- 從資料結構與演算法以及設計模式角度去學習View的繪製流程資料結構演算法設計模式View
- 設計模式 - Bridge 橋模式設計模式
- 從設計模式角度看OkHttp原始碼設計模式HTTP原始碼
- 設計模式 | 橋接模式(bridge)設計模式橋接
- 重學Java設計模式-學習筆記(1)Java設計模式筆記
- 從JavaScript學習設計模式-02單例模式JavaScript設計模式單例
- 從JavaScript學習設計模式-01原型模式JavaScript設計模式原型
- 設計模式——從介面的角度切入靜態工廠模式設計模式
- 重學設計模式-單例模式設計模式單例
- 《設計模式》 - 6. 橋接模式( Bridge )設計模式橋接
- 設計模式的征途—8.橋接(Bridge)模式設計模式橋接
- C#設計模式-橋接模式(Bridge Pattern)C#設計模式橋接
- C#設計模式系列:橋接模式(Bridge)C#設計模式橋接
- JAVA設計模式之 橋接模式【Bridge Pattern】Java設計模式橋接
- 設計模式(五)橋接模式Bridge == Pointer To Implementation設計模式橋接
- 設計模式(一)學習設計模式的好處設計模式
- 設計模式學習設計模式
- 從原始碼學習設計模式之模板方法原始碼設計模式
- 設計模式學習——代理模式設計模式
- C#設計模式(8)——橋接模式(Bridge Pattern)C#設計模式橋接
- 從設計模式角度分析Promise:手撕Promise並不難設計模式Promise
- 使用Lambdas重構工廠設計模式設計模式
- Java設計模式學習Java設計模式
- MapReduce設計模式學習設計模式
- FSM 設計模式學習設計模式
- 從感性角度學習原型/原型鏈原型
- 設計模式-建立型模式學習設計模式
- 設計模式學習-物件池模式設計模式物件
- 設計模式學習-物件模板模式設計模式物件
- 設計模式學習-原型模式設計模式原型
- 設計模式學習-單例模式設計模式單例
- 設計模式學習-建造者模式設計模式
- 設計模式學習-工廠模式設計模式