Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Who should be responsible for selecting the appropriate derived class?

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.

like image 385
Andrew Keller Avatar asked Jul 02 '12 16:07

Andrew Keller


2 Answers

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.

like image 72
Sergey Kalinichenko Avatar answered Oct 20 '22 01:10

Sergey Kalinichenko


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.

like image 3
Robert Levy Avatar answered Oct 20 '22 03:10

Robert Levy