2011-04-25 68 views
7

我知道一點關於Object Oriented design,但我不確定如何在代碼中使用這些原則。這裏就是我的工作:我該如何設計這個更好? (避免使用面向對象設計的switch語句)

public void Query(Agency agency, Citation queryCitation) { 
     queryCitation.AgencyCode = agency.AgencyCode; 

     switch (agency.ClientDb.Type) { 
      case "SQL": 
       QueryOracle(agency, queryCitation); 
       break; 
      case "PIC": 
       QueryPick(agency, queryCitation); 
       break; 
     } 
    } 

(。其中大部分是從NHibernate的,我用舊的數據庫系統的工作對象和我重構它的一部分轉換成代碼庫)很顯然,我可以做這裏有不同的東西,所以我不需要具有相同輸入的不同數據庫查詢的重複函數。它應該僅僅根據代理對象知道是使用Oracle數據庫還是使用Pick數據庫連接。 (如果你從來沒有聽說過Pick數據庫,那麼在我開始在這裏工作之前我一直沒有聽說過,我們通過HTTP請求來查詢它,所以它不是SQL。)

我應該做一個接口,用於例如被稱爲「ClientDbConnection」,然後讓實現該接口,代碼來查詢數據庫移動到這些,然後有一些像「agency.clientDb.Query(queryCitation)」兩班替換這整個功能?我想我在這裏大聲思考,但任何意見都將不勝感激。

回答

11

是機構自己控制的班?如果這樣做這樣的事情:

public abstract class GenericDb 
{ 
    public abstract void Query(parms); 
} 

在你的機構類,你可以有

public GenericDb ClientDb {get; set;} 

然後有一個SQLDB類,如:

public class SqlDb : GenericDb 
{ 
    public void Query(parms); 
} 

public class PicDb : GenericDb 
{ 
    public void Query(parms); 
} 

那麼這個代碼:

public void Query(Agency agency, Citation queryCitation) { 
     queryCitation.AgencyCode = agency.AgencyCode; 

     switch (agency.ClientDb.Type) { 
      case "SQL": 
       QueryOracle(agency, queryCitation); 
       break; 
      case "PIC": 
       QueryPick(agency, queryCitation); 
       break; 
     } 
    } 

變成

public void Query(Agency agency, Citation queryCitation) { 
     queryCitation.AgencyCode = agency.AgencyCode; 
     agency.ClientDb.Query(queryCitation); 
    } 

由於繼承,它會知道ClientDb具有GenericDb的基類。它將通過ClientDb參數的類型知道它應該運行SqlDb還是PicDb或Oracle等。

3

我會重構利用一個接口。我可能會做它像:

public interface IQuery 
{ 
    void Execute(Agency agency, Citation query); 
} 

public class OracleQuery : IQuery 
{ 
    // Implementation 
} 

public class PickQuery : IQuery 
{ 
    // Implementation 
} 

然後,您可以更改該機構類來存儲一個IQuery對象的實例,而不是(或除了)ClientDb對象:

public class Agency 
{ 
    public IQuery Query { get; set; } 
} 

而且然後在您的初始化代碼中(您通常會設置ClientDb屬性),則可以將實例設置爲適當的IQuery實現:

agency.Query = new PickQuery(); 
2

ADO.NET有一組泛型類:的DbCommand,的DbConnection,等等...這也實現了另一套通用接口:IDbCommand的,的IDbConnection,等...

所以,你可以使用它們,但它最終可能會變得相當複雜。您的解決方案的優點是非常易讀。另外,也許挑數據庫沒有任何ADO.NET提供者...

PS:我雖然更換類型物業類型,並使用枚舉來代替。

5

您可能希望在此實施戰略模式。基本上,switch語句中的每個可能的「類型」都將成爲它自己的一個實現相同接口的類。

Applying the Strategy Pattern

然後,您可以使用一個工廠方法,需要一個「類型」的值作爲參數。該方法將返回正確的類(其返回類型是上面提到的接口)。

0

有兩種OOP解決方案polymorphismVisitor pattern

+0

你能解釋一下嗎?在Stackoverflow上,僅鏈接答案不是很受歡迎。 – 2016-05-27 14:23:11

2

要編寫更少的代碼,但提高可讀性,您可以使用代表爲每個數據庫開發代碼的代碼級別。這可以很容易地擴展並且非常可讀。考慮到更多的功能方法,你可以得到類似於

void Query(Agency agency, Citation queryCitation) 
{ 
    Dictionary<string, Action<Agency, Citation>> QueryMap = new Dictionary<string, Action<Agency, Citation>> 
    { 
     { "SQL", QueryOracle}, 
     { "PIC", QueryPic} 
    }; 


    queryCitation.AgencyCode = agency.AgencyCode; 

    QueryMap[agency.ClientDb.Type](agency, queryCitation); 
}