Java switch statement multiple cases

前端 未结 13 1106
后悔当初
后悔当初 2020-11-27 14:43

Just trying to figure out how to use many multiple cases for a Java switch statement. Here\'s an example of what I\'m trying to do:

switch (variable)
{
    c         


        
13条回答
  •  迷失自我
    2020-11-27 15:00

    One Object Oriented option to replace excessively large switch and if/else constructs is to use a Chain of Responsibility Pattern to model the decision making.

    Chain of Responsibility Pattern

    The chain of responsibility pattern allows the separation of the source of a request from deciding which of the potentially large number of handlers for the request should action it. The class representing the chain role channels the requests from the source along the list of handlers until a handler accepts the request and actions it.

    Here is an example implementation that is also Type Safe using Generics.

    import java.util.ArrayList;
    import java.util.List;
    
    /**
    * Generic enabled Object Oriented Switch/Case construct
    * @param  type to switch on
    */
    public class Switch>
    {
        private final List> cases;
    
        public Switch()
        {
            this.cases = new ArrayList>();
        }
    
        /**
         * Register the Cases with the Switch
         * @param c case to register
         */
        public void register(final Case c) { this.cases.add(c); }
    
        /**
         * Run the switch logic on some input
         * @param type input to Switch on
         */
        public void evaluate(final T type)
        {
            for (final Case c : this.cases)
            {
                if (c.of(type)) { break; }
            }
        }
    
        /**
         * Generic Case condition
         * @param  type to accept
         */
        public static interface Case>
        {
            public boolean of(final T type);
        }
    
        public static abstract class AbstractCase> implements Case
        {
            protected final boolean breakOnCompletion;
    
            protected AbstractCase()
            {
                this(true);
            }
    
            protected AbstractCase(final boolean breakOnCompletion)
            {
                this.breakOnCompletion = breakOnCompletion;
            }
        }
    
        /**
         * Example of standard "equals" case condition
         * @param  type to accept
         */
        public static abstract class EqualsCase> extends AbstractCase
        {
            private final T type;
    
            public EqualsCase(final T type)
            {
                super();
                this.type = type;
            }
    
            public EqualsCase(final T type, final boolean breakOnCompletion)
            {
                super(breakOnCompletion);
                this.type = type;
            }
        }
    
        /**
         * Concrete example of an advanced Case conditional to match a Range of values
         * @param  type of input
         */
        public static abstract class InRangeCase> extends AbstractCase
        {
            private final static int GREATER_THAN = 1;
            private final static int EQUALS = 0;
            private final static int LESS_THAN = -1;
            protected final T start;
            protected final T end;
    
            public InRangeCase(final T start, final T end)
            {
                this.start = start;
                this.end = end;
            }
    
            public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
            {
                super(breakOnCompletion);
                this.start = start;
                this.end = end;
            }
    
            private boolean inRange(final T type)
            {
                return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
                        (type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
            }
        }
    
        /**
         * Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
         *
         * @param args command line arguments aren't used in this example
         */
        public static void main(final String[] args)
        {
            final Switch integerSwitch = new Switch();
            final Case case1 = new EqualsCase(1)
            {
                @Override
                public boolean of(final Integer type)
                {
                    if (super.type.equals(type))
                    {
                        System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
                        return super.breakOnCompletion;
                    }
                    else
                    {
                        return false;
                    }
                }
            };
            integerSwitch.register(case1);
            // more instances for each matching pattern, granted this will get verbose with lots of options but is just
            // and example of how to do standard "switch/case" logic with this pattern.
            integerSwitch.evaluate(0);
            integerSwitch.evaluate(1);
            integerSwitch.evaluate(2);
    
    
            final Switch inRangeCaseSwitch = new Switch();
            final Case rangeCase = new InRangeCase(5, 100)
            {
                @Override
                public boolean of(final Integer type)
                {
                    if (super.inRange(type))
                    {
                        System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
                        return super.breakOnCompletion;
                    }
                    else
                    {
                        return false;
                    }
                }
            };
            inRangeCaseSwitch.register(rangeCase);
            // run some examples
            inRangeCaseSwitch.evaluate(0);
            inRangeCaseSwitch.evaluate(10);
            inRangeCaseSwitch.evaluate(200);
    
            // combining both types of Case implementations
            integerSwitch.register(rangeCase);
            integerSwitch.evaluate(1);
            integerSwitch.evaluate(10);
    
        }
    }
    

    This is just a quick straw man that I whipped up in a few minutes, a more sophisticated implementation might allow for some kind of Command Pattern to be injected into the Case implementations instances to make it more of a call back IoC style.

    Once nice thing about this approach is that Switch/Case statements are all about side affects, this encapsulates the side effects in Classes so they can be managed, and re-used better, it ends up being more like Pattern Matching in a Functional language and that isn't a bad thing.

    I will post any updates or enhancements to this Gist on Github.

提交回复
热议问题