以您的PDF示例为起点,让我们来看一下。
http://en.wikipedia.org/wiki/Single_responsibility_principle
单一责任原则建议一个对象应该只有一个目标。请记住这一点。
http://en.wikipedia.org/wiki/Separation_of_concerns
关注分离原则告诉我们,类不应具有重叠功能。
当您查看这两者时,他们建议逻辑仅在有意义的情况下才应放在一个类中,并且仅当该类负责这样做时才应使用。
现在,在您的PDF示例中,问题是,谁负责打印?有什么道理?
第一个代码段:
Pdf pdf = new Pdf();
pdf.Print();
这个不好。PDF文档不会自行打印。它由... ta da!..打印机打印。因此,您的第二个代码段要好得多:
Pdf pdf = new Pdf();
PdfPrinter printer = new PdfPrinter();
printer.Print(pdf);
这是有道理的。Pdf打印机可打印pdf文档。更好的是,打印机不应是PDF打印机或照片打印机。它应该只是一台打印机,它可以打印出发送给它的东西,以其最大的功能。
Pdf pdf = new Pdf();
Printer printer = new Printer();
printer.Print(pdf);
这很简单。将方法放在有意义的地方。显然,它并不总是那么简单。以您的国家/地区统计数据为例:
Country m = new Country("Mexico");
double ratio = m.GetDebtToGDPRatio();
您担心的是,可能没有n个统计信息,因此不应将它们归为Country类。那是真实的。但是,如果您的模型仅要求提供特定的统计信息,则此建模示例实际上可能很好。
在这种情况下,您可以在逻辑上说一个国家应该能够计算自己的统计信息,具体取决于您的模型和手头的要求。
事情就在这里:您有什么要求?您的需求将驱动您满足这些需求的建模环境的方式。
如果确实有大量/可变的统计信息,那么第二个例子更有意义:
Country m = new Country("Mexico");
DebtStatistics ds = new DebtStatistics();
double usRatio = ds.GetDebtToGDPRatio(m);
更好的是,有一个抽象超类或称为Statistics的接口,该接口将国家作为参数:
interface StatisticsCalculator // or a pure abstract class if doing C++
{
double getStatistics(Country country); // or a pure virtual function if in C++
}
DebtToGDPRatioStatisticsCalculator类实现StatisticsCalculator...。
InfantMortalityStatisticsCalculator类实现了StatisticsCalculator ...
等等等等。这导致以下内容:泛化,委托,抽象。统计收集被委派给概括特定抽象(统计收集API)的特定实例。
我不知道这是否能100%回答您的问题。毕竟,我们没有基于不可侵犯的法律的可靠模型(就像EE的人们一样。)您所能做的就是在有意义的地方放一些东西。这是您需要做出的工程决策。最好的办法是真正熟悉OO原则(以及一般的良好软件建模原则)。