2012-11-28 37 views
1

多個版本在你的公司,說你有下面的代碼:如何使用仿製藥,而不是繼承有什麼

public abstract Phone 
{ 
    public int PhoneID {get;set;} 
    public string PhoneNumber {get;set;} 
} 

public CustomerPhone : Phone 
{ 
    public int CustomerID {get;set;} 
} 

public AccountPhone : Phone 
{ 
    public int AccountID {get;set;} 
} 

什麼這是應該的意思是,我們有多種類型的手機,有些是客戶電話,一些帳戶電話等...

問題是「這是可能的,如果是這樣,那麼怎麼樣?」看起來最簡單的方法就是擁有一個可插入類型的通用Phone類,然後在需要時使用該類型的信息(AccountID或CustomerID)來使用。我也檢查,看看這是可能的,而不DI(無論是通過構造函數,方法或屬性。)

我在我的頭上什麼會是這個樣子:

public interface IUsePhone 
{ 
    int GetOwnerID(); 
} 

public class Phone<T> where T : IUsePhone 
{ 
    //all of Phone's properties from above. 

    public int GetOwnerID() 
    { 
     //return T or item or something's GetOwnerID(); 
    } 
} 

public class Account : IUsePhone 
{ 
    private int _accountID; 

    //other Account members, including an AccountID property. 

    public int GetOwnerID() 
    { 
     return _accountID; 
    } 

    public Phone<Account> Phone { get; set; } 
} 

public class Customer : IUsePhone 
{ 
    private int _customerID; 

    //other Customer members, including an CustomerID property. 

    public int GetOwnerID() 
    { 
     return _customerID; 
    } 

    public Phone<Customer> Phone { get; set; } 
} 

這沒有按」因爲Phone的GetOwnerID()目前沒有辦法返回它的所有者的GetOwnerID()結果。我希望從客戶角度來看,最終的結果可能會是這個樣子:

Account myAccount = new Account(); 
myAccount.AccountID = 10; 

int ownerID = myAccount.Phone.GetOwnerID(); //this would return 10. 
+0

編譯和運行時被混淆了。鑑於缺少更好的東西,可以使用'return default(T)'進行編譯,儘管這不是非常有用。考慮是否有「SetPhone(IUsePhone ..)」方法。請注意,即使他們在'IUsePhone'上工作,'賬戶/客戶'也不會統一到'電話'。 – 2012-11-28 21:18:04

+0

這可能聽起來很愚蠢,實際上可能沒有辦法做我正在談論的事情。我希望不必像你提到的那樣使用反射或依賴注入(通過SetPhone方法)。我越想越想,一旦你把這兩個選項拿走,看起來就越不可能,但我知道有一些真的很聰明在那裏的人,所以我認爲這是值得一試。 – IWriteApps

+1

這看起來像工廠模式的工作(http://www.dofactory.com/Patterns/PatternFactory.aspx) –

回答

4

我認爲你需要問自己,爲什麼你想這樣做。

如果你真的想了一堆不同的類型,所有這些都在Phone合同履行,你是一個界面更好,再加上也許是一個抽象的基本實現:

public interface IPhone 
{ 
    int PhoneID {get;set;} 
    string PhoneNumber {get;set;} 
} 

public abstract AbstractPhoneBase : IPhone 
{ 
    public int PhoneID {get;set;} 
    public string PhoneNumber {get;set;} 
} 

public CustomerPhone : AbstractPhoneBase 
{ 
    public int CustomerID {get;set;} 
} 
+0

@ f0x :)這是個好主意! :) –

+0

這或多或少是我們現在在我們設計中的。我正在研究的是看看我們是否可以避免擁有「CustomerPhone」和「SomeOtherTypePhone」,因爲它們都是完全相同的,減去所有者ID的NAME。即CustomerPhone中的CustomerID和SomeOtherTypePhone中的SomeOtherTypeID。 – IWriteApps

+0

如果確實如此,請添加一個屬性'字符串AdditionalIdDescripton',並將泛型屬性'字符串AdditionalId'或其他適用於您的詳細用例的內容。如果你需要將這些值映射到一個小的閉集,你可以使用'enum'而不是一個字符串。 – SAJ14SAJ

0

我覺得你的例子是很好 - 只是缺少實現IUsePhone(賬戶,客戶等)的擁有者的實例的構造函數。

嘗試將此添加到您的Phone<T>類中。

public IUsePhone Owner { get; private set; } 

    public Phone(T owner) 
    { 
     this.Owner = owner; 
    } 

    public int GetOwnerID() 
    { 
     return this.Owner.GetOwnerID(); 
    } 

注意:在你的榜樣,不要忘記你必須設置電話屬性之前myAccount.Phone.GetOwnerID();可以被調用。

如果你正在做的是這樣我會下去的抽象基類路徑已經建議並設定手機在沿線的基本方法:

public virtual void SetPhoneNumber<T>(string number) 
    { 
     this.Phone = new Phone<T>(this); 
     this.Phone.Number = number; 
    } 

所以,你的使用率最終會看起來像這個:

Account myAccount = new Account(); 
    myAccount.AccountID = 10; 

    myAccount.SetPhoneNumber("123456"); 

    int ownerID = myAccount.Phone.GetOwnerID(); // this would return 10.