I have a platform that I am writing that provides a default set of modules to the developer by which I am hoping that they extend to provide more custom functionality during run time. The following code snippet is the default module hierarchy:
package com.test.core;
public abstract class Module {
    public abstract void performAction();
}
package com.test.fun;
public class AModule extends Module {
    @Override
    public void performAction() {
        // Perform action A
    }
}
package com.test.fun;
public class BModule extends Module {
    @Override
    public void performAction() {
        // Perform action B
    }
}
package com.test.fun;
public class CModule extends Module {
    @Override
    public void performAction() {
        // Perform action C
    }
}
There is a module engine that will create modules at the start of the app's instance and stores these modules in a HashMap where [key=name; value=Module]. Because of the nature of my backend and app, I must use name as the key and to identify modules.
public Module createModule(String name) throws Exception {
    Module module = null;
    Class moduleClass = null;
    // Find class by name, default to using <name>Module as the class name
    // might throw exception
    String className = name = "com.test.fun." + name + "Module";
    moduleClass = Class.forName(className);
    if (moduleClass == null) {
        // quit, nothing to do
    } else {
        // create the module
        module = (QPComponent) moduleClass.getConstructor().newInstance();
    }
    return module;
}
Assuming that that AModule is a binary and I cannot update its implementation, I want to add more behaviour to the module with they key "A" such as the following.
package com.test.custom;
public class ExtendedModuleA extends AModule {
    @Override
    public void performAction() {
        super.performAction();
        // Do some more to add behaviour to AModule
    }
}
How would I have to revise the architecture to enable a developer to register their custom implementation of a module for key "A" so that when the app starts, the app will grab the custom ExtendedModuleA version instead of the default AModule version?
One way I was thinking, that doesn't seem pretty is the following:
public class ModuleRegistry {
    // Assume singleton
    HashMap<String, Class<Module>> registry;
    public ModuleRegistry() {
    }
    private void init() {
        registry = new HashMap<String, Class<Module>>();
        registry.put("A", ExtendedModuleA.class);
        // no extension for B
        registry.put("C", CModuleExtra.class);
        // developers add more entries to "register" more extended modules here for the future
    }
    public Class<Module> getExtendedModuleClass(String name) {
        return registry.get(name);  
    }
}
Is there a design pattern or tool library that can help me with this kind of problem? I am currently only thinking of this solution because I remember things like Spring or Dagger or Android's manifest were you have to register your classes in order for them to be used or picked up by the system. I am already using Dagger in my app, but my modules themselves need ObjectGraphs, so it is might have a chicken and the egg catch-22 situation.
 
     
     
    