Using Dependency inversion to avoid depending on volatile/heavy packages

After reading this mulitple implementations answer by @stevengj, I implemented a slightly more complex strategy. Using a type hierarchy allows the “interface” to comprise more than a single method.

I now have a method optimize(f, ::AbstractDistributionFitOptimizer, lower, upper) that calls the actual optimization routine. By specializing this method, different implementations can be used.
Method DistributionFits.set_optimizer(::AbstractDistributionFitOptimizer) configures the Optimizer used by the package.
Again, Requires.jl is used to automatically set the default, if the Optim.jl package is in scope.

I am happy about critical feedback and advice on a Julian way of managing project dependencies in a way that higher-level code does not depend on lower-level code.