Object-oriented refactoring

This is quite a heavy refactoring. The main change is to split up the code into the Worker and EncodingFactory classes. The benefit is the key and encoding then belong to the worker instance, and thereby don't need to passed around in the method calls as they were before.

There's a lot of other small refactorings here and there but they'd be more easily seen by running through the history rather than the finished product.