这是否给代码带来了异味或违反了SOLID原则?
public string Summarize()
{
IList<IDisplayable> displayableItems = getAllDisplayableItems();
StringBuilder summary = new StringBuilder();
foreach(IDisplayable item in displayableItems)
{
if(item is Human)
summary.Append("The person is " + item.GetInfo());
else if(item is Animal)
summary.Append("The animal is " + item.GetInfo());
else if(item is Building)
summary.Append("The building is " + item.GetInfo());
else if(item is Machine)
summary.Append("The machine is " + item.GetInfo());
}
return summary.ToString();
}正如您所看到的,我的Summarize()绑定到实现类,如Human、Animal等。
此代码是否违反了LSP?(还有其他可靠的原则吗?)
发布于 2010-09-04 00:10:22
考虑到OP对this answer的评论,我认为最好的方法是创建一个自定义容器类来替换具有containsHumans()和containsAnimals()等方法的IList<IDisplayable> displayableItems,这样您就可以将讨厌的非多态代码封装在一个地方,并保持Summarize()函数中的逻辑清晰。
class MyCollection : List<IDisplayable>
{
public bool containsHumans()
{
foreach (IDisplayable item in this)
{
if (item is Human)
return true;
}
return false;
}
// likewise for containsAnimals(), etc
}
public string Summarize()
{
MyCollection displayableItems = getAllDisplayableItems();
StringBuilder summary = new StringBuilder();
if (displayableItems.containsHumans() && !displayableItems.containsAnimals())
{
// do human-only logic here
}
else if (!displayableItems.containsHumans() && displayableItems.containsAnimals())
{
// do animal-only logic here
}
else
{
// do logic for both here
}
return summary.ToString();
}当然,我的例子过于简单和做作。例如,无论是作为Summarize() if/else语句中逻辑的一部分,还是围绕整个代码块,您都需要遍历displayableItems集合。此外,如果在MyCollection中覆盖Add()和Remove(),并让它们检查对象的类型并设置标志,那么您可能会获得更好的性能,这样您的containsHumans()函数(和其他函数)就可以简单地返回标志的状态,而不必在每次调用它们时迭代集合。
发布于 2010-09-03 23:48:32
我闻到了一点东西..。
如果您的类都实现了IDisplayable,那么它们都应该实现自己的逻辑来显示自己。这样你的循环就会变得更干净:
public interface IDisplayable
{
void Display();
string GetInfo();
}
public class Human : IDisplayable
{
public void Display() { return String.Format("The person is {0}",
GetInfo());
// Rest of Implementation
}
public class Animal : IDisplayable
{
public void Display() { return String.Format("The animal is {0}",
GetInfo());
// Rest of Implementation
}
public class Building : IDisplayable
{
public void Display() { return String.Format("The building is {0}",
GetInfo());
// Rest of Implementation
}
public class Machine : IDisplayable
{
public void Display() { return String.Format("The machine is {0}",
GetInfo());
// Rest of Implementation
}然后,您可以将您的循环更改为更清晰的东西(并允许类实现自己的显示逻辑):
foreach(IDisplayable item in displayableItems)
summary.Append(item.Display());发布于 2010-09-03 23:50:01
看起来IDisplayable应该有一个用于显示名称的方法,所以您可以将该方法简化为如下所示
summary.Append("The " + item.displayName() + " is " + item.getInfo());https://stackoverflow.com/questions/3637377
复制相似问题