I recently wrote a class library that includes some objects that model certain types of files. For example, there is an abstract Document
class, with derived classes PdfDocument
(concrete) and OfficeDocument
(abstract, with concrete derived classes such as WordDocument
and ExcelDocument
), etc.
Currently the way clients create a new object is by selecting the appropriate derived class and passing it the byte array. So for example, if I have a byte array of a PdfDocument and a WordDocument, I would do something like:
var wordDocument = new WordDocument(wordDocumentByteArray);
var pdfDocument = new PdfDocument(pdfDocumentByteArray);
Is this acceptable design, that the client must know what derived class to use? Or would I be better off hiding all but the abstract Document
class and using something such as an abstract factory pattern to return the correct derived type? e.g.:
var wordDocument = DocumentFactory.GetDocument(wordDocumentByteArray, "docx");
// pass file extension so we know what the file is
Note that the derived types do not add additional properties/methods to the abstract class, they just implement the abstract methods in different ways.
The second approach is much better than the first one, because it hides the very fact of existence of Word and Pdf documents from the users of your library. This becomes especially important when you decide to add more document types - e.g. Rtf, Html, and so on: the users would get the benefits of the newly added types without having to recompile their code. In fact, they would not even notice that you have changed anything: if done right, their code will "just work" with the documents of type they have never knew existed.
P.S. If you can scan the byte array and figure out the correct type from it, your API can "earn some points for style" by eliminating the second parameter.
If the derived types don't add any properties/methods and you have the technical ability to determine what type to use for a given byte[], I would not even make the derived classes public... they just increase the surface area of stuff the consumer will have to parse when learning your library. Just have a static factory method like like public static Document OpenDocument(byte[] data)
in the Document class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With