2011-10-21 92 views
4

我有一個預訂系統,可讓您預訂預訂,修改現有預訂並取消現有預訂。我正在研究界面隔離原則,並且我想知道應該使界面變得多薄,如果我違反了單一責任原則。我INTIAL設計是:瘦和胖界面之間的「細線」是什麼?

interface IReservation 
{ 
    void Book(); 
    void Modify(); 
    void Cancel(); 
} 

,但轉念一想,如果一個預約系統,並不需要實現這些方法的預約之一,只是關心預訂例如什麼,所以我做了以下內容:現在

interface IBook 
{ 
    void Book(); 
} 


interface IModify 
{ 
    void Modify(); 
} 

interface ICancel 
{ 
    void Cancel(); 
} 

我可以做這樣的事情:

interface IReservation : IBooking 
{ 


} 

interface IReservation : IBooking, IModify 
{ 


} 

所以這個問題變成了我將它變得如此稀疏。此外,爲界面設計名稱變得更加困難,例如,我不喜歡IModify或ICancel(它們看起來像是我應該在IReservation界面上的方法)。你如何確定應該進入一個接口的內容以及應該被分成另一個接口,類等的內容......

+0

這不是直截了當的告訴你是否要遠離這一點。如果你直接用這個例子 - 是的。國際海事組織(IMO)在這種情況下(小型)會採用YAGNI原則來決定,但如果它變得更大,其他因素就變得更加重要。 – kubal5003

+0

不想用我有限的答案來破壞你的問題,但我可以爲這兩種方法說點什麼。第一個,最直觀的,每個人都會開始。第二個更像框架級接口,比如IEnumerable等。這是一次性工作還是試圖創建一個框架? – kroonwijk

回答

5

你有兩件事情你必須考慮你的界面的範圍看時:

  1. 是否有意義要求每個IReservation來實現這些成員?
  2. 參考成員X沒有會員Y是否有意義?

首先是你已經涵蓋的內容,並得出「否」的結論。第二,雖然同樣重要。在沒有其他任何事情的情況下,將某些事情想象爲「可以修改」是否有意義?如果不是,請考慮製作IReservationIModifiableReservation或其他功能組合。

例如,看起來好像CancelModify緊密相連,因此可能希望將它們放在一起放在IModifiableReservation上,然後讓您的課程實現該接口。

正如你所見,這似乎有點過於細化。

+0

感謝您的簡單而有效的答案。 – Xaisoft

+0

不需要創建脂肪IReservation,但添加另一個細粒度的IBookableReservation。我已經在下面的答案中提出了我的考慮http://stackoverflow.com/a/16492280/52277 –

0

如果你的應用程序確實需要支持不同類型的保留,並且稍後一些通用邏輯應該能夠處理所有這些 - 我會建議爲每個服務類型和每個預留本身提供單個接口的單獨接口,這個想法 - 預留提供了一組服務,所以你可以公開接口提取的服務列表,並且去掉多個接口實現爲每個預訂系統。只是每個服務創建一個類,並通過預約的構造函數註冊服務:

var reservationWithBooking = 
    new Reservation(new List<IReservationService { new BookingService() }); 

var reservationWithCancellation = 
    new Reservation(new List<IReservationService { new CancellationService(); }); 

var mixedReservation = 
    new Reservation(new List<IReservationService 
          { 
           new BookingService(), 
           new CancellationService() 
          }); 

接口:

interface IReservationService 
{  
} 

interface IBookingService : IReservationService 
{ 
    void Book(...); 
} 

interface ICancellationService : IReservationService 
{ 
    void Cancel(...); 
} 

interface IReservation 
{ 
    IEnumerable<IReservationService> Services { get; } 
} 

class Reservation : IReservation 
{ 
    private IList<IReservationService> services; 

    public Reservation(IEnumerable<IReservationService> services) 
    { 
     this.services = new List<IReservationService>(services); 
    } 

    public IEnumerable Services<IReservationService> 
    { 
     get 
     { 
      return this.services; 
     } 
    } 
} 
1

我會建議由Adam Robinson

interface IModifiableReservation 
{ 
    void Modify(); 
    void Cancel(); 
} 

你並不需要創建IReservation接口有兩個接口

interface IBookableReservation 
{ 
    void Book(); 
} 

as suggested,而是直接來自IBookableReservation和IModifiableReservation繼承類。客戶端可以使用一個或兩個接口。

沒有必要創建一個接口,它只是複製單個類的公共方法。 如果接口的名稱與帶有「I」前綴的類相同,則表示它是一個代碼異味,因爲它表示它是一個1:1 relationship between the interface and the concrete classes that implement它。

Reused Abstractions Principle (RAP)

http://martinfowler.com/bliki/InterfaceImplementationPair.html

使用接口時,你不會有多個 實現是額外的努力,把一切都在sync.Furthermore 它隱藏的情況下,你實際上提供多個 實現。

+0

'Foo'可以實現'IFoo'接口,因爲還有一個'FakeFoo'類用作模擬。這根本不一定是代碼味道。 –

+0

我們正在測試一個邏輯接口(而不是關鍵字接口),並且這個邏輯接口是由類還是接口提供並不重要。 movking框架大部分支持虛擬方法的模擬。不要使用實際上不需要的接口膨脹代碼庫。 請參閱http://stackoverflow.com/questions/12174304/is-it-recommended-to-mock-concrete-class –

相關問題