繁体   English   中英

我是否正确使用接口?

[英]Am I using interfaces correctly?

我使用界面的主要原因是简化单元测试。 但是我感觉我不明白如何100%使用接口。

这是我正在尝试做的简化版本:

public interface IPlan
{
    List<Plan> GetPlans(IPlan plan);
    List<Plan> GetAllPlans();
    List<string> DoSomethingElse();
}

public class Plan : IPlan
{
    List<Plan> GetPlans(IPlan plan)
    {
        // 
    List<Plan> planList = plan.GetAllPlans();

    //
    // Do stuff with planList...
    //
}

为了设置单元测试,我需要能够模拟Plan类并从GetAllPlans返回计划的一组列表,所以我看到我应该在此处使用该接口,以便可以正确模拟它。 我也了解(或至少我认为)我应该将IPlan对象传递给GetPlans,然后我应该使用该IPlan对象来调用GetAllPlans ...但是这种设置似乎不对劲。

我设置不正确吗? 传递与所在类相同类型的IPlan似乎很奇怪(我打算传递作为计划的IPlan)。 有什么建议吗?

我认为,您的困惑源于您计划班级的落后性质。 您可能拥有一个类,该类可能封装了一些计划数据,但还提供了处理其自身列表的方法。

没有看到更多代码,很难确定,但是您可能应该GetPlansGetAllPlans移到另一个处理计划列表的类中。 然后,将他们的签名更改为

List<IPlan> GetPlans();
List<IPlan> GetAllPlans();

即使是通用类,也可能受T : IPlan约束,因此签名为:

List<T> GetPlans();
List<T> GetAllPlans();

您正在正确实施它。 接口中定义的每个方法都必须在您的具体类中实现。

我对您的问题不了解的是...

“我传递一个与它所在的类相同类型的IPlan似乎很奇怪(我将传递一个作为计划的IPlan)。”

你能澄清一下吗?

如果您的意思是List GetPlans(),那么这样的事情是完全可以预期的。 您打算退还计划的集合。

接口定义了每个类实现都应该实现的一些框架方法。 在此基础上签订了“合同”,以确保类将实现此接口。 这也意味着您可以执行诸如插件之类的操作,在此您知道您具有IPlugin接口,并且可以使用say Reflection加载已实现此接口的程序集并开始在类中调用方法。

也许您需要一个称为Plan的实体类,然后将当前实现IPlan的Plan类重命名为PlanOperations之类。 似乎该课程将完成工作,并且您的Plan只是一个可能有设置者的实体/对象

接口是一种合约 ,旨在(可能)应用于许多对象。 它基本上告诉您的应用程序,实现接口的任何对象都将实现您在接口中指定的方法。

它是为松散耦合而设计的。 而不是您的方法接受一个Plan对象,例如:

public bool DoSomething(Plan plan)
{
//....
}

您可以使用IPlan:

public bool DoSomething(IPlan plan)
{
//....
}

这意味着在运行时,您可以将任何东西传递给该方法,只要该方法实现IPlan。

这也意味着,对于单元测试,您可以创建IPlan的虚拟实现(例如,如果IPlan通常与DB通信,则您不希望它在测试中发生)并通过它-这样您就可以进行测试方法中的代码,而不是该方法及其在Plan内部调用的任何代码。

嗯,从技术上讲,您的实现是正确的,但是对于接口在其方法中使用该接口的具体实现来说,这似乎很奇怪。 好像IPlan试图“做太多”。

相反,我会有这样的东西:

public interface IPlanRepository
{
    IEnumerable<IPlan> GetPlans(IPlan plan);
    IEnumerable<IPlan> GetAllPlans();
    IEnumerable<string> DoSomethingElse();
}

public class PlanRepository : IPlanRepository
{
    IEnumerable<IPlan> GetPlans(IPlan plan)
    {
        // fill a List with Plans
    }
    IEnumerable<IPlan> planList = GetAllPlans();
    {
        // fill a List with Plans
    }
    //
    // Do stuff with planList...
    //
}

public interface IPlan
{
   // properties and methods relating to a Plan (NOT how to "get" a Plan)
}

public class Plan : IPlan
{
    // implementation of properties and methods
}

请注意,我还将List返回类型更改为更通用的IEnumerable接口。 如果您使用的是ORM,这将使您在实现中灵活返回任何返回IEnumerable<Plan>例如List<Plan>Plan[]IQueryable<Plan>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM