[英]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)。 有什么建议吗?
我认为,您的困惑源于您计划班级的落后性质。 您可能拥有一个类,该类可能封装了一些计划数据,但还提供了处理其自身列表的方法。
没有看到更多代码,很难确定,但是您可能应该GetPlans
和GetAllPlans
移到另一个处理计划列表的类中。 然后,将他们的签名更改为
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.