【问题标题】:Using interface to differentiate implementation使用接口区分实现
【发布时间】:2013-12-04 23:40:59
【问题描述】:

这是我的具体场景,其中包含一个接口及其实现:

IPerson {string Name;}

American : IPerson {string Name;}
Asian : IPerson {string Name;}
European : IPerson {string Name;}

People = new List<IPerson>(); // This list can have American, Asian and/or European

当我访问People 列表时,我需要区分美国、亚洲和欧洲,它们可以共享相同的界面。使用所有实现 IPerson 的附加接口(IAmerican、IAsian、IEuropean)是否很好,并使用它来区分实现类,例如:

IAmerican : IPerson {}
IAsian : IPerson {}
IEuropean : IPerson {}

American : IAmerican {string Name;}
Asian : IAsian {string Name;}
European : IEuropean {string Name;}

People = new List<IPerson>();
People.Add(new American());
People.Add(new Asian());
People.Add(new European());

var americans = People.OfType<IAmerican>(); // Getting all Americans from People

新接口没有多大用处,只是用来隔离对象。这是一个好方法还是我应该在 IPerson 中实现一些类型属性来区分它的实现?

【问题讨论】:

  • 对我来说没有意义。放置一个名为Nationality 的属性并使用.Where()
  • 我会选择@HighCore.. 选择一个属性。假设您需要添加专业,您会添加属性专业还是单独的类,如AmericanManagerAsianStudent.?对我来说没有意义
  • 真正的问题是:为什么需要以不同的方式对待人员集合中的人员?你应该重新考虑你的整体设计。

标签: c# oop interface


【解决方案1】:

您不必执行第二步,您的第一步也应该可以。

void Main()
{
    var people = new List<IPerson>();
    people.Add(new American { Name = "jack"});
    people.Add(new American { Name = "John"});
    people.Add(new Asian { Name = "ho"});

    Console.WriteLine (people.OfType<American>());

}

public interface IPerson {
    string Name {get; set;}
}

class American : IPerson {public string Name {get; set; }}
class Asian : IPerson {public string Name {get; set; }}
class European : IPerson {public string Name {get; set; }}

输出:

杰克
约翰

该列表将每个对象定义为它们的共同点 (IPerson),但这并不意味着它失去了对实际对象的跟踪。我认为没有必要创建过时的接口。

话虽如此:我更喜欢组合而不是继承。 AmericanEuropean 有什么区别?在 Person 类中保留一个属性(使其成为类而不是接口),以指示一个人的区域性。

【讨论】:

    【解决方案2】:

    类型不仅是可用的鉴别器。您可以直接询问对象:

    enum Continent { Europe, Asia, America }
    
    public interface IPerson 
    {  
        string Name { get; set; }
        Continent Continent { get; set; }
    }
    
    public class Asian : IPerson
    {
        public Continent Continent
        {
            get 
            {
               return Continent.Asia;
            }
        }
    }
    

    这就是接口的意义——类以自己特定的方式实现其功能。

    【讨论】:

      【解决方案3】:

      我会选择房产。

      enum PersonType
      {
          American, Asian, European
      }
      
      interface IPerson
      {
          string Name { get; set; }
          PersonType Type { get; }
      }
      
      American : IPerson
      {
          public string Name { get; set; }
          public PersonType Type { get { return PersonType.American; } }
      }
      

      并查询Americans:

      var americans = People.Where(p => p.Type == PersonType.American);
      

      您可能应该为 enum 找到一个更好的名称,但这里重要的是概念,而不是名称。

      【讨论】:

        【解决方案4】:

        您所描述的一切都表明您会从添加额外接口中受益。

        即使实现不同,如果接口相同

        • 拥有相同的公共成员
        • 公共成员在概念上做同样的事情

        但它仍然没有真正给你买任何东西。

        接口的全部意义在于,即使类对外部世界的行为相同,但它们不一定具有相同的实现。这就是为什么它被称为Interface 而不是Implementation

        【讨论】:

        • 我也是这么想的。也许这个问题过于简单化了,这不是问题。
        【解决方案5】:

        根据某个值选择正确的具体类型非常适合工厂模式。我建议您实施工厂以选择正确的IPerson。另一方面,如果您计划针对IPerson 实施控制反转,那么最好编写一个接口并采用多接口方法。

        【讨论】:

          【解决方案6】:

          可能不会。接口的重点是定义不同对象之间的相似性。如果您的算法必须知道每个 IPerson 是什么类型的人,那么您通过接口的抽象获得的收益很少。此外,如果您尝试创建一种新型 IPerson 却忘记为其添加案例,您的算法将会崩溃(可能以奇怪的方式)。

          事实上,即使是带有开关的 Type 属性也可能不是最佳方法。 Visitor Pattern 是您可能会发现有用的常见设计策略。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-11-10
            • 1970-01-01
            • 1970-01-01
            • 2015-11-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多