Make code more Generic in Java

与世无争的帅哥 提交于 2020-01-05 04:29:23

问题


I have a Trigger Manager scenario where I delegate the triggers (in other-words subscribe triggers) to different handlers.

For now I have three handler types, I use a switch-case with enum (enum here is the handler type) to redirect to correct handler.

But my code seems not extensible, its not generic and it doesn't follow SOLID principle. Imagine if I need to have more handler

I will be eventually coming and editing my switch case code and I will have more cases where it affects the cyclomatic complexity of my code

Below is my exact code snippet

private static TriggerContext getTriggerContext(TriggerHandlerType triggerHandlerType) throws TriggerHandlerException {
    switch (triggerHandlerType) {
        case DASHBOARD_HANDLER:
            triggerContext = new TriggerContext(new DashboardTriggerHandler());
            return triggerContext;
        case COMPONENT_HANDLER:
            triggerContext = new TriggerContext(new ComponentTriggerHandler());
            return triggerContext;
        case WIDGET_HANDLER:
            triggerContext = new TriggerContext(new WidgetTriggerHandler());
            return triggerContext;
        default:
            LOGGER.error(MIS_CONFIGURED_REQUEST_IS_PROVIDED);
            throw new TriggerHandlerException(TRIGGER_HANDLER_TYPE_GIVEN_IS_NOT_CONFIGURED_IN_THE_LIST_OF_TRIGGER_HANDLERS);

    }

}

Can someone help me to enhance this code in-which I can make it more generic and avoid cyclomatic complexity and follow SOLID Principle along with some design pattern.


回答1:


I think you mean "make code more dynamic", and your problem comes from using objects as primitives.

Rather than switching on the enum object, your enum objects should contain the type to be instantiated:

enum TriggerHandlerType {
    DASHBOARD {
        @Override
        TriggerHandler create() {
            return new DashboardTriggerHandler();
        }
    },
    COMPONENT_HANDLER {
        //...
    };

    abstract TriggerHandler create();
}

getTriggerContext can then call create() to instantiate the handler:

private static TriggerContext getTriggerContext(TriggerHandlerType triggerHandlerType) throws TriggerHandlerException {
    return new TriggerContext(triggerHandlerType.create());
}



回答2:


I am not sure about the overall design structure, but the switch can be replaced with a newHandler() method on the enum.

private static TriggerContext getTriggerContext(TriggerHandlerType triggerHandlerType)
    throws TriggerHandlerException
{
    return new TriggerContext(triggerHandlerType.newHandler());
}

In the enum you would implement the method for each type enum as

enum TriggerHandlerType {
    DASHBOARD_HANDLER
    {
        Handler newHandler() { return new DashboardHandler(); }
    },
    ...;
    abstract Handler newHandler();
}



回答3:


You could use a map of configurations for that:

// All your triggers classes should implement this interface
interface TriggerHandler {}

// For example:
public static class DashboardTriggerHandler implements TriggerHandler {
}

// Create your configuration
static Map<TriggerHandlerType, Class> contexts;
static {
    contexts = new HashMap<>();
    contexts.put(TriggerHandlerType.DASHBOARD_HANDLER, DashboardTriggerHandler.class);
    contexts.put(TriggerHandlerType.COMPONENT_HANDLER, ComponentTriggerHandler.class);
    contexts.put(TriggerHandlerType.WIDGET_HANDLER, WidgetTriggerHandler.class);
}

// Return your instance through reflection
public static TriggerContext getTriggerContext(TriggerHandlerType triggerHandlerType) throws TriggerHandlerException, IllegalAccessException, InstantiationException {

    Class className = contexts.get(triggerHandlerType);

    if (className == null) {
        throw new TriggerHandlerException();
    }

    return new TriggerContext((TriggerHandler)className.newInstance());
}


来源:https://stackoverflow.com/questions/39044863/make-code-more-generic-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!