When “if else”/“instance of” are inevitable, how do we improve the design apart from using visitor pattern?

有些话、适合烂在心里 提交于 2019-12-05 08:27:14

If you still know the types at compile time you can use a helper class:

class Function {
}

class Average extends Function {
}

class Sum extends Function {
}

class Max extends Function {
}

class FunctionHelper {
  public Number calculate(Average a) {
    return null;
  }

  public Number calculate(Sum s) {
    return null;
  }

  public Number calculate(Max a) {
    return null;
  }

  public Number calculate(Function a) {
    return null;
  }

}

Generally you'd make the helper methods static but you are not restricted to that - there are some rather interesting things you can do with multiple flavours of helper class.

these objects are purely plain object stateless objects just represent the semantic.

Sounds like you want to use enums then instead of regular objects.

Then you can use switch statements and have the compiler check that you handled all cases.

enum Function { Average, Sum, Max }

i just stumbled over the Chain of Responsibilty pattern which might solve your Problem:

For this we create a handler class for every Function starting with a common base class

public abstract class FunctionHandler {
    private FunctionHandler nexthandler = null;

    protected abstract boolean isConditionMet(Function function);

    protected abstract void calculate(Function function);

    public void handleFunction(Function function) {
        if(function == null) {
            return;
        }

        if (isConditionMet(function)) {
            calculate(function);
        } else {
            if (nexthandler != null) {
                nexthandler.handleFunction(function);
            }
        }
    }

    public FunctionHandler setNexthandler(FunctionHandler nexthandler) {
        this.nexthandler = nexthandler;
        return nexthandler;
    }
}

next we create the concrete handlers:

public class Averagehandler extends FunctionHandler {
    @Override
    protected boolean isConditionMet(Function function) {
        return function instanceof Average;
    }

    @Override
    protected void calculate(Function function) {
        // do average stuff
    }
}

public class SumHandler extends FunctionHandler {
    @Override
    protected boolean isConditionMet(Function function) {
        return function instanceof Sum;
    }

    @Override
    protected void calculate(Function function) {
        // do sum stuff
    }
}

public class MaxHandler extends FunctionHandler {
    @Override
    protected boolean isConditionMet(Function function) {
        return function instanceof Max;
    }

    @Override
    protected void calculate(Function function) {
        // do max stuff
    }
}

now look for a nice central place to put your chain together (e.g. a utility class)

public final class FunctionUtil {
    public static final FunctionHandler HANDLER;

    static {
        HANDLER = new Averagehandler();
        HANDLER.setNexthandler(new SumHandler()).setNexthandler(new MaxHandler());
    }
}

now you can start replacing your if-else-blocks with calls to FunctionUtil.HANDLER.handleFunction(function);

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