2012-07-02 98 views
8

我最近编写了一个类库,其中包含一些对某些类型的文件建模的对象。例如,有一个抽象Document类,与派生类PdfDocument(混凝土)和OfficeDocument(摘要,用混凝土派生类如WordDocumentExcelDocument)等谁应该负责选择适当的派生类?

目前客户端的方式创建一个新的目的是通过选择适当的派生类并将其传递给字节数组。因此,举例来说,如果我有一个PdfDocument和WordDocument的字节数组,我会做这样的事情:

var wordDocument = new WordDocument(wordDocumentByteArray); 
var pdfDocument = new PdfDocument(pdfDocumentByteArray); 

这是可以接受的设计,客户端必须知道派生类中使用?或者我会更好地隐藏除抽象Document类以外的所有东西,并使用诸如抽象工厂模式之类的东西来返回正确的派生类型?例如: -

var wordDocument = DocumentFactory.GetDocument(wordDocumentByteArray, "docx"); 
// pass file extension so we know what the file is 

注意,派生类型不添加额外的属性/方法抽象类,他们只是以不同方式实现的抽象方法。

+0

绝对是第二个选项。允许将来更容易扩展,并且意味着当添加新的更适合的类型时,人们花更少的时间更新类声明。 –

+0

'Document'类是否具有最终用户需要处理给定'Document'的所有内容,还是偶尔(或经常)需要访问特定于更多派生类型的功能? – Servy

+0

@Servy是的,'Document'类有一个公共抽象方法。所有派生类只包含受保护的和私有的帮助方法(加上重写的公共方法),其唯一目的是实现一个公共方法。 – Andrew

回答

9

第二种方法比第一种方法好得多,因为它隐藏了来自库的用户的Word和Pdf文档存在的事实。当您决定添加更多文档类型时,这变得尤为重要 - 例如Rtf,Html等等:用户可以从新添加的类型中获益,而无需重新编译他们的代码。事实上,他们甚至不会注意到你已经改变了任何事情:如果做得对,他们的代码将“与他们从未知道的类型的文档一起工作”。

P.S.如果您可以扫描字节数组并从中找出正确的类型,那么通过消除第二个参数,API可以“为样式赢得一些点”。

+0

谢谢。我一定会查看是否能从字节数组中找出类型,在我的示例中添加扩展的唯一原因是因为从一些非常简短的研究看来,可能没有确定文件的确定方法每次都从二进制表示中键入。 – Andrew

3

如果派生类型没有添加任何属性/方法,并且您有技术能力来确定给定字节[]使用的是什么类型,我甚至不会公开派生类......他们只是增加消费者在学习图书馆时必须解析的东西的表面积。在Document类中只需要一个像public static Document OpenDocument(byte[] data)这样的静态工厂方法。

+0

谢谢。我将使用工厂方法而不是抽象工厂(对于我需要完成的工作看起来似乎是过度的)。 – Andrew

+0

*“如果派生类型不添加任何属性/方法”*这是一个相当大的“如果”。有很多事情可以用一个已知的文件类型来完成,而这个文件类型不能用通用的“文档”来完成。 – Servy

+0

@Servy我同意但我的图书馆的目的,我没有在问题中说明,它所做的只是对二进制数据进行一些修改。功能非常明确,所以在这种情况下,我认为这个假设是可以的(首先只需要派生类是因为修改及其实现因文件类型而异)。 – Andrew