使用界面的主要原因是使单元测试变得容易。但我觉得我不理解如何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)似乎很奇怪。对此有何建议?
答案 0 :(得分:2)
我认为,你的混乱源于你的计划课的性质。你有一个类可能封装了一些计划数据,但它也提供了处理自身列表的方法。
在没有看到更多代码的情况下,很难确定,但您应该首先将GetPlans
和GetAllPlans
移动到另一个处理计划列表的类中。然后将其签名更改为
List<IPlan> GetPlans();
List<IPlan> GetAllPlans();
甚至可能使该类具有通用性,约束于T : IPlan
因此签名为:
List<T> GetPlans();
List<T> GetAllPlans();
答案 1 :(得分:0)
您正在正确实施它。接口中定义的每个方法都必须在具体类中实现。
我在你的问题中不明白的是......
“我传递的IPlan类型与它所在的类型相同似乎很奇怪(我将通过一个计划中的IPlan传递)。”
你可以澄清一下吗?如果你的意思是List GetPlans(),那么这样的事情就完全没问题了。您计划返回一系列计划。
接口定义了每个实现的类应该实现的一些框架方法。这个基础是一个“契约”,以保证类将实现这个接口。这也意味着你可以做插件,你知道你有一个IPlugin接口,你可以使用say reflection来加载已经实现了这个接口的程序集,并开始在类中调用方法。
也许您需要一个名为Plan的实体类,然后将当前的Plan类重命名为Planlan或Planoperations。似乎这个类将完成工作,而您的计划只是一个可能获得设置者的实体/对象
答案 2 :(得分:0)
接口是合同,旨在(可能)应用于许多对象。它基本上告诉您的应用程序,实现接口的任何对象将实现您在接口中指定的方法。
它专为松耦合而设计。而不是接受Plan对象的方法,例如:
public bool DoSomething(Plan plan)
{
//....
}
你可以把它带到IPlan:
public bool DoSomething(IPlan plan)
{
//....
}
这意味着在运行时,您可以将任何内容传递给该方法,只要它实现IPlan。
这也意味着,对于单元测试,您可以创建一个IPlan的虚拟实现(例如,如果IPlan通常与数据库通信,您不希望它在您的测试中发生)并传递它 - 以便您只测试方法中的代码,而不是测试方法和它在Plan内部调用的任何内容。
答案 3 :(得分:0)
嗯,技术上你的实现是正确的,但是接口在其方法中使用该接口的具体实现似乎很奇怪。看起来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
接口。这使您可以灵活地在实现中返回任何,如果您使用的话,会返回IEnumerable<Plan>
,例如List<Plan>
,Plan[]
或IQueryable<Plan>
ORM。