扩展接口实现?

Extend Interface Implementation?

我有一个小型对象工厂,可以创建两种类型的对象。现在我想向第二个对象添加新方法但不更改接口,因为我也必须在第一个对象中实现该方法。怎么做?

public class LookupFactory
{
    public ILookups CreateLookups()
    {
        ILookups dbLookup = null;
        var databaseType = ConfigurationManager.AppSettings["databaseType"].ToString();

        switch (databaseType.ToLower())
        {
            case "oracle":
                dbLookup = new Lookups();
                break;
            case "mssql":
                dbLookup = new SqlLookups();
                break;
        }

        return dbLookup;
    }
}

我的界面是这样的:

public interface ILookups
{
    List<Region> GetRegions(string language);

    List<Industry> GetIndustries(string language);

    List<Dimension> GetDimensions(string language);

    List<SubjectType> GetSubjectTypes(string language);
 }

我只想将方法 GetPeople 添加到 SqlLookups 对象。

嗯,如果两个 classes 实现一个接口,它们必须实现所有方法。所以,如果你想在你的接口中添加新方法,你必须在 LookupsSqlLookups 中实现它。 可能的解决方案:

  1. 创建新界面IExtendedLookups : ILookups并添加新界面 IExtendedLookups 并使 class SqlLookups : IExtendedLookups 的方法 您的工厂应该 return ILookups 但稍后在代码中您必须检查 returned 值:

    var lookups = factory.CreateLookups();
    var extendedLookups = lookups as IExtendedLookups;
    if (extendedLookups != null)
    {
        //...call extendedLookups.GetPeople();
    }
    
  2. 向 ILookups 添加新方法,在两个 classes 中实现,但在 Lookups 中这样做:

    public List<People> GetPeople()
    {
        throw new NotSupportedException();
    }
    

你必须问自己这个问题 "consumer side"。

作为起点,我会这样做:

  1. 生成仅由特定 classes 实现的精致接口:

    public interface ILookups
    {
        List<Region> GetRegions(string language);
        List<Industry> GetIndustries(string language);
        List<Dimension> GetDimensions(string language);
        List<SubjectType> GetSubjectTypes(string language);
    
        // maybe add this
        // this makes it clear to the consumer that it could receive an extended lookup
        // one class returns "this", the other "null" 
        IExtendedLookUps GetExtendedOrNull { get;}
    }
    
    public interface IExtendedLookups : ILookups
    {
        List<People> GetPeople();
    }
    
     void consumerCode()
     {
        ILookups lookups = factory.CreateLookups();
    
        // code that works for both cases
        lookups.GetRegions("en");
    
        // do something special if it implements IExtendedLookups
        if (lookups is IExtendedLookups)
        {
            var extendedLookups = lookups as IExtendedLookups;
            extendedLookups.GetPeople();
        }
        // or with the additional interface property:
        var maybeExtendedLookups = lookups.GetExtendedOrNull;
        if (maybeExtendedLookups  != null)
        {
            maybeExtendedLookups.GetPeople();
        }
    
     }
    
  2. 如果额外的方法只与单一目的相关(例如生成某个报告),那么可以在界面中包含此报告生成。

  3. 如果有合适的 "default" 值(如您的情况下的空列表),请将其添加到另一个 class。如果没有合适的默认就不要做。

总结一下:这完全取决于你想如何使用它。从使用到实现的设计而不是相反!