【发布时间】:2020-08-19 04:26:14
【问题描述】:
假设我有以下界面
interface ILeague
{
string ShowSquad();
}
以下实现它们的类
class EPL : ILeague
{
public string ShowSquad()
{
return "EPL players collection";
}
}
class LaLiga: ILeague
{
public string ShowSquad()
{
return "La-liga player Collection";
}
}
我正在消费这个界面,如下图
public string ShowLeaguePlayers(ILeague leagueDataProvider)
{
return leagueDataProvider.ShowSquad();
}
现在,根据我所在的联赛,我想显示不同的数据。有时是 EPL,有时是 LaLiag。这种切换可以发生在同一个执行周期中。 我尝试了以下方法
class LeagueDataProvider : ILeague
{
private ILeague m_Provider;
private string league;
private void SetContext()
{
// Have some logic to figure out the league
league = "EPL";
if (league.Equals("EPL"))
{
m_Provider = new EPL();
}
else
{
m_Provider = new LaLiga();
}
}
public string ShowSquad()
{
SetContext();
return m_Provider.ShowSquad();
}
}
我已将我的客户端代码修改为以下
void ShowData()
{
ILeague Dataprovider = new LeagueDataProvider();
Console.WriteLine(ShowLeaguePlayers(Dataprovider));
}
// copied again for easy viewing
public string ShowLeaguePlayers(ILeague leagueDataProvider)
{
return leagueDataProvider.ShowSquad();
}
这很好用,但每次我调用 ShowSquad 时,它都必须检查联赛并获取数据。有没有更好的方法来做到这一点?
我想在这里实现什么:
根据联赛,我想在调用 ShowSquad 时获得不同的数据。 我应该能够在 UT 中模拟 ILeague,并且将来可能会有更多 ILeague 的实现,所以我想避免修改和重新测试消耗它们的组件
【问题讨论】:
-
是的,很难知道你为什么要这样设计它,你要分离什么问题,以及你想要实现什么。您可能希望您的
LeagueDataProvider作为一个通用类。虽然很难说 -
我应该可以在我的 UT 中模拟 ILeague。这是我重构这段代码的主要原因。其他原因是,未来可能会有更多的 ILeague 实现,所以我想避免修改将来使用它们的类
-
我不会把
LeagueDataProvider变成ILeague,因为它不是。它或多或少是一个工厂。你希望它包含或产生一个ILeague,而不是实现一个。谷歌“c#类工厂模式示例” -
@Andy 这是我最初的想法,将 LeagueDataProvider 作为一个工厂,返回一个我可以使用的 ILeague。但是要编写 UT,我应该让我的工厂实现一个接口并在我的 UT 中模拟它。我不太确定工厂的良好做法是否应该实现接口
-
你可以让它实现一个接口。喜欢
public interface ILeagueFactory { ILeague CreateLeague(); }
标签: c# oop design-patterns