I actually liked where you went with it, other than I'm not sure I'd give the same interface between a file transfer protocol and a database protocol. I would have given two different interfaces, so if you switched from FTP to Telnet, or Curl, or SCP all of those could be built the same.
I don't necessarily think the same is true for MongoDB, MySQL, Postgres, Oracle, etc, however, all of those would have the same process as each other, just not the same as FTP, Telnet, etc.
I really wish people would utilize interfaces more often (this comes from my .NET background). Interfaces are a godsend for APIs and forcing classes to abide by a specific implementation. It is unfortunately so many get it wrong or refuse to use it.
@K_Wolfe ; one thing that really has helped me choose between composition and inheritance is using the "is a" rule, but on top of that, if I ever had the thought, "Man, I wish I could inherit both X and Y", I know I screwed up somewhere and I need to re-evaluate what I've done. Inheritance complicates things, and more inheritance only leads to further complication.
Let me leave you with this thought. Where I previously worked a contractor built our original web service that allowed third parties to get quotes from our system. The VERY base class of the 13 level inheritance was named ErrorClass (I'm not kidding!). The only thing I can tell you now, is at least he knew where his code was heading. Everything sucked, it threw more errors than returning success messages, etc. After reworking it for a couple of years (it took us years to get an architecture that could easily be swamped out), our largest inheritance level was 3. We only needed that third level for a special implementation of a project and once everything was transferred over, it went down to 2, but I think this will bring home the point (inheritance isn't bad, but it's complicated, and you need to understand why you are doing it and you are doing it for the right reasons).