2012-01-06 52 views
4

我有一系列對象,我用LINQ to SQL映射到數據庫中。這些表格高度規範化。我要抽象我的問題。我在數據庫中實現了五個中心實體。然後我有一系列其他對象,我想實現這五個實體中的一個或全部。僞多繼承

假設我正在實施一種體育課(比如運動隊)。這五個實體是五大體育項目;棒球,籃球,足球,曲棍球,足球。我想爲每個體育場明確實施一堂課。

這是一個例子,揚基體育場已經舉辦棒球,曲棍球和足球比賽。我希望它實現這3個接口中的每一個。 StadiumBaseClass是我的抽象基類,與我的數據庫接口。 StadiumBaseClass實現了所有5個主要的運動界面。我不想在所有可能的體育場館中使用相同的代碼來實現IBaseball接口,我希望它在StadiumBaseClass中實現一次。

我這個例子,我只想實現3,這是做這個的最好方法嗎?它有點單調,但不完全?

class YankeeStadium : IBaseball, IHockey, IFootball 
{ 
    StadiumBaseClass _Stadium {get; set;} 

    // IBaseball 
    public IBaseball.Whatever {get { return _Stadium.Baseball;} } 

    // IFootball 
    public IFootball.Whatever {get { return _Stadium.Hockey;} } 

    // IHockey 
    public IHockey.Whatever {get { return _Stadium.Hockey;} } 
} 
+0

你可以閱讀抽象工廠模式,看看它是否與你需要的類似。 – 2012-01-06 00:57:41

+0

你的「抽象基類」就像你的描述所說的那樣是「StadiumBaseClass」,或者是你的代碼顯示的所有體育場封裝的數據對象? – dasblinkenlight 2012-01-06 01:23:50

+0

你是C#4.0還是4.0之前? – dasblinkenlight 2012-01-06 01:36:54

回答

0

下面是一個替代方法(我們已經使用了類似的,但不知道事情會如何使用您的LINQ實現對應):

有無StadiumBaseClass實現每個基本功能的接口,然後暴露虛擬財產的實現類可用於a)指示它支持的接口,以及b)根據需要更改默認行爲。

例如,假設以下接口:

public interface IBaseball 
    { 
     void Whatever(); 
    } 
    public interface IHockey 
    { 
     void Whatever(); 
    } 
    public interface IFootball 
    { 
     void Whatever(); 
    } 
    public interface IBasketball 
    { 
     void Whatever(); 
    } 
    public interface ISoccer 
    { 
     void Whatever(); 
    } 

你的基類,看起來是這樣的:

public class StadiumBaseClass : IBaseball, IBasketball, IHockey, IFootball, ISoccer 
    { 

     #region IBaseball Members 

     public virtual bool IBaseballImplemented 
     { 
      get 
      { 
       return false; 
      } 
     } 

     void IBaseball.Whatever() 
     { 
      // Do something 
     } 

     #endregion 

     #region IBasketball Members 

     public virtual bool IBasketballImplemented 
     { 
      get 
      { 
       return false; 
      } 
     } 

     void IBasketball.Whatever() 
     { 
      // Do something 
     } 

     #endregion 

     #region IHockey Members 

     public virtual bool IHockeyImplemented 
     { 
      get 
      { 
       return false; 
      } 
     } 

     void IHockey.Whatever() 
     { 
      // Do something 
     } 

     #endregion 

     #region IFootball Members 

     public virtual bool IFootballImplemented 
     { 
      get 
      { 
       return false; 
      } 
     } 

     void IFootball.Whatever() 
     { 
      // Do something 
     } 

     #endregion 

     #region ISoccer Members 

     public virtual bool ISoccerImplemented 
     { 
      get 
      { 
       return false; 
      } 
     } 

     void ISoccer.Whatever() 
     { 
      // Do something 
     } 

     #endregion 
    } 

這會使你的個人體育場類爲:

class YankeeStadium : StadiumBaseClass 
    { 
     public override bool IBaseballImplemented 
     { 
      get 
      { 
       return true; 
      } 
     } 
     public override bool IHockeyImplemented 
     { 
      get 
      { 
       return true; 
      } 
     } 
     public override bool IFootballImplemented 
     { 
      get 
      { 
       return true; 
      } 
     } 
    } 
+0

我將不得不投入界面來調用Whatever()方法。 – Mark 2012-01-06 01:49:46

+0

是的,帶有繼承類,但如果繼承類需要它們,也可以將選定的接口方法作爲基類中的具體方法公開。好處在於,這種方法可以消除基本類數據從您在問題中顯示的繼承類的多餘返回。該代碼將直接在stadiumbaseclass中實現,不必在其繼承者中重複。 – 2012-01-06 02:01:58

+0

如果downvoters會解釋他們的邏輯,那肯定會有幫助。沒有解釋的下調對任何人都沒有幫助,坦率地說,這是懦弱的。 – 2012-01-06 18:21:56

-1

我認爲你應該退後一步,看看一些四種模式的幫派。這正是他們設計的解決方案。我建議你開始查看訪問者模式。 vistior模式可以使很多項目(在你的案例中)在它們之間執行共同的行爲。在這裏看到:http://www.dofactory.com/Patterns/PatternVisitor.aspx

的四種模式的團伙的名單在這裏:http://www.dofactory.com/Patterns/Patterns.aspx

也許別人可能會建議另一種模式來看看。可能是裝飾者模式也看起來很有希望。 (我之前沒有使用過decarator模式)。我認爲最終你不應該與OO作鬥爭,而是尋找可能出現的常見場景的已發佈解決方案。

2

我不認爲你應該繼續使用繼承。而不是YankeeStadium類,你應該有一個帶有名稱屬性的Stadium類。

同樣,你應該有一個屬性,如HasHockey或者只要Hockey屬性返回null,如果它不適用。

+0

在我的例子中沒有繼承......如果(對象是IHockey)確定球場是否有曲棍球信息,我可以做。我不必擁有財產。 – Mark 2012-01-06 01:45:19

1

我建議僅僅擁有每個球場的每個運動屬性,所以你可以調用

Stadium.Baseball.Fixtures 
Stadium.Hockey.Teams 

當一個特定的球場不允許運動,返回Null Object這對於體育運動;

iceRink.Baseball.Available // false 
iceRink.Baseball.Fixtures // the empty list 

這樣應該可以幫助您避免多重繼承的問題,特別是,這樣的代碼

((IBaseball)stadium).Fixtures 
2

這似乎是一個共同的面向對象的建模問題的變化 - 在過去,我已經看到它構成教育機構的問題,其中給定的人可能是學生,導師,講師,標記,研究員等中的一個或多個。

我見過的最佳解決方案是Peter CoadJeff De Luca作爲Nebulon Archetypal Domain Shape,也被稱爲Color Modelling

在你的情況,實際的體育場將是你的Places。既然你想明確地將每個體育場作爲一個班級來實施,那麼每個體育場都將代表實際的體育場館。擁有共同的抽象基類可能會有所幫助。課堂上的屬性將描述體育場的物理屬性 - 例如它的實際地址等等。

每個要支持不同的運動(你列出的棒球,籃球,足球,曲棍球和足球)將被實現爲Role類,說BaseballStadiumBasketballStadiumFootballStadiumHockeyStadiumSoccerStadium。課堂上的屬性將描述託管該特定運動的具體特徵(座位容量可能會有所不同,例如,從一項運動到另一項運動)。

+0

我也建議將數據訪問層與業務層分離。如果業務邏輯相當抽象,並且數據庫實體高度規範化,那麼嘗試聯合使用DAL和BL最可能以代碼混亂結束。 – 2012-01-06 01:57:12

+0

我打算/已經從業務層分離數據。 – Mark 2012-01-06 04:12:40