I created a library in Scala. It's a parser that comes with different implementations. The trait that abstracts from everything looks something like this (simplified):
trait Parser {
def parse(in: Array[Byte]): Array[Byte]
}
The concrete parser implementations that are provided by the library extend the trait above (nothing spectacular).
class FastParser(...) extends Parser...
class HighQualityParser(...) extends Parser...
Since I dont want clients to have dependencies on the concrete implementation classes (I even thought about making them package private), I'm using a companion object of the trait which offers access to the parsers without exposing their type:
object Parser {
def getFastParser: Parser = new FastParser(...)
def getHighQualityParser: Parser = new HighQualityParser(...)
}
Users should also be able to use their own implementations of the Parser
trait if they want to.
However, I'm not sure if this is the best approach.
- Are there any general disadvantages with this approach?
- What about hiding the two implementations using access modifiers? From a client perspective, is there a reason to have acces to the implementations?
You may think those are very basic questions about loose coupling and abstraction. This is not necessarily the case, I'm using dependency injection frameworks and similar things all the time myself. However; I've never published a library before and find it quite difficult to provide something that can be used by everyone in a flexible way without being to complicated.