2012-11-28 19 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.