我正在开发一个应用程序,用于将用户上传的图像/文档的数据库和目录从我们的生产服务器传输到开发服务器。该应用程序是用Coldfusion编写的,但我不认为该语言与这个问题相关 - 它更多的是结构/架构问题,而不是语言特有的问题。
我将为我的示例编写伪代码,所以请不要选择语法。
当我看到类继承演示时,它通常像class Student extends Person() {}
这样简单。显然,学生是一个更专业的人,所以这是有道理的。
在我的应用程序中,我有一个类Site()
,其中包含相关信息,如DSN,文件上载目录等。我在一个类中执行我的SQL导出,而我的文件上载导出在另一个类中,这是从站点类(伪代码)中调用的:
class Site {
public function exportSql() {
sqlExport = new sqlExport(this.dsn);
sqlExport.createDumpAndZipItAndStuff();
}
public function exportUploads() {
uploadsExport = new uploadsExport(this.uploadDirectory);
uploadsExport.copyAndZipFilesAndStuff();
}
}
除了控制从应用程序前端请求的流量流之外,Site类不会执行任何操作,其他所有内容都将传递给其中一个导出类。
这对我来说很好,但我想构建它正确。现在,我必须将Site的属性传递给导出类的构造函数,然后使用这些参数设置导出类的属性。这会造成很多重复。
让导出类继承Site类以便我可以直接访问属性是否合适?导出类不是更专业的站点,就像我之前给出的Person / Student示例一样。相反,他们只是为Site类执行繁重的工作。
如果这不适合继承,我应该如何构建应用程序?正如我之前所说,我现在正在做的方式有效,但我想借此机会更多地了解设计模式,并以有意义的方式编写代码。
答案 0 :(得分:5)
当是类别的东西时,应该使用继承。
就像狗是一种动物,因此它应该继承动物。
导出不是网站,因此不应该继承。
您正在寻找的是Composition。 导出应将引用保存到其导出的网站。然后,您可以在构建时将Site对象传递给它,并且可以随时从站点获取数据。
答案 1 :(得分:2)
导出不应扩展您的Site类,因为Exports的内容不是Sites的一部分内容的成员。继承被过度使用,在这种情况下,Composition更有意义。可以通过使用依赖注入来优化现有对象模型和提高可测试性的一种方法。
在对象实例中调用“new”会使对象模型更脆弱,更难测试。您可以将导出器的实例注入Site类。
旁注:我将导出类命名为 nouns (SQLExporter,而不是SQLExport)。这是一种风格化的东西,但我认为它更好地传达了类的作用:它是一个被委派了导出数据的角色的对象。
public setSQLExporter( SQLExporter exporter )
{
variables.sqlExporter = arguments.exporter;
// set some properties on exporter here, like the DSN
variables.sqlExporter.dsn = this.dsn;
}
public setUploadsExporter( UploadsExporter exporter )
{
variables.uploadsExporter = arguments.exporter;
// set some properties on exporter here, like the upload directory
variables.uploadsExporter.uploadDirectory = this.uploadDirectory;
}
public function exportSql() {
variables.sqlExporter.createDumpAndZipItAndStuff();
// or maybe your generalize the interface to these exporters and do something like
// variables.sqlExporter.export();
}
public function exportUploads() {
variables.uploadsExporter.copyAndZipFilesAndStuff();
// or maybe your generalize the interface to these exporters and do something like
// variables.uploadsExporter.export();
}
然后,在您的主应用程序中(或者首先实例化Site对象的任何内容):
thisSite = new Site(...);
// Get some Exporters
thisSite.setSQLExporter( new SQLExporter() );
thisSite.setUploadsExporter( new UploadsExporter() );
// Trigger exports
thisSite.exportSql();
thisSite.exportUploads();
这打开了使用Mock Objects直接测试Site的大门,而不需要有数据库或文件系统来与之交谈。如果你使用像ColdSpring这样的DI框架,框架可以为你做这个接线。