我有一个“IPartyCountService”接口,用于计算客户数量和供应商数量。
实施类“PartyCountService”使用类型检查来检查该方是客户还是供应商。
实现类PartyCountService使用类型检查是否会产生代码异味?
任何反馈,评论和批评都表示赞赏。
public interface IPartyCountService
{
int GetTotalNumberOfCustomers();
int GetTotalNumberOfSuppliers();
}
internal class PartyCountService:IPartyCountService
{
IPartyRepository _partyRepository;
public PartyCountService(IPartyRepository partyRepository)
{
_partyRepository = partyRepository;
}
public int GetTotalNumberOfCustomers()
{
var counter = 0;
foreach(var customer in _partyRepository.GetAll())
{
if (customer is Customer) counter++;
}
return counter;
}
public int GetTotalNumberOfSuppliers()
{
var counter = 0;
foreach (var customer in _partyRepository.GetAll())
{
if (customer is Supplier) counter++;
}
return counter;
}
}
public interface IPartyRepository
{
IList<IParty> GetAll();
}
internal class PartyRepository:IPartyRepository
{
public IList<IParty> GetAll()
{
// put together all parties, including customers and suppliers
return allParties;
}
}
internal class Customer:IParty{}
internal class Supplier:IParty{}
public interface IParty{}
答案 0 :(得分:2)
我会使用.OfType&lt;&gt;扩展方法。
return _partyRepository.GetAll().OfType<Customer>().Count();
编辑:如下面的SP所述,这使得一些更清洁的代码,但不一定能修复气味。
答案 1 :(得分:1)
对我来说感觉不对,但你可以做出一点改变就是这个。
return _partyRepository.GetAll().Count(p => p is Customer);
答案 2 :(得分:1)
也许IParty应该有一种方法来询问你在计算“顾客”时感兴趣的东西吗?
答案 3 :(得分:1)
我认为您不应该隐藏公共API中的Customer
和Supplier
。但是,建议您使用ICustomer
和ISupplier
接口替换它们。基于接口的设计基于组件的最前端(即其公共API)将帮助您很自然地实现更好的设计。
关于类型检查和计数:我没有看到显式动态类型检查是坏事。但是,通过使用接口,它们在语义上变得更加自然。另外,为了保存明确的foreach
和一对{ }
,我不认为只有无处不在引入类似LINQ的语句。
答案 4 :(得分:1)
客户和供应商是否存储在partyRepository中的单个异构集合中?似乎简单地挂在一组客户和一个单独的供应商集合上要容易得多;然后它可以暴露像GetCustomers(),GetSuppliers()或Get&lt; T&gt;()这样的函数。
使用这种方法,您仍然可以实现GetAll() - 将2个集合“联合”在一起非常容易。比过滤异构集合更容易(可能性能更好)。
答案 5 :(得分:0)
它有点臭,但不是我见过的(或自己完成的)最臭的东西。几点想法:
return _partyRepository.GetAll().OfType<Supplier>().Count();
答案 6 :(得分:0)
首先,我认为这是一个选择问题。您必须知道每种可能的替代方案所涉及的权衡:
备选方案(1)的优点是更简洁,并且对OO采用友好方法。 (但是,请记住,当您查看对象的具体类型时,您正在打破多态性。)
备选方案(2)的优点是,首先,您不依赖元数据来了解对象类型。其次,is
调用比检查变量类型更昂贵。因此,请确保您能够轻松获得性能。
编辑:现在我看一下它,你正在抽象出一个接口类型,然后再将它转换回它的具体类型。这是为什么?如果使用集合的类知道不同的类型,它应该直接访问存储在那里的类型。