繁体   English   中英

内部枚举的策略模式

[英]Strategy pattern with inner enum

我试图从我的代码中删除大的switch语句,我认为基于我现有的枚举的策略模式会很好。 这个概念就像:

public class MyStrategy {

    public MyStrategy() {
        Option.Option1.setMethodToExecute(this::action1);
        Option.Option2.setMethodToExecute(this::action2);
    }

    public void executeChoosenMethod(int i) {
        Option.values()[i].execute();
//        instead of
//        switch(convertItoOption()) {
//            case Option1:...
//            case Option2:...
//        }
    }

    private void action1() {
        System.out.println("action1");
    }

    private void action2() {
        System.out.println("action2");
    }

    private enum Option {
        Option1, Option2;

        private InvokeAction methodToExecute;

        public void setMethodToExecute(InvokeAction methodToExecute) {
            this.methodToExecute = methodToExecute;
        }

        public void execute() {
            methodToExecute.execute();
        }
    }

    @FunctionalInterface
    private interface InvokeAction {
        void execute();
    }
}

所以我可以使用它:

public class StrategyTest {
    public static void main(String[] args) {
        MyStrategy strategy = new MyStrategy();
        //user choose 0 or 1
        strategy.executeChoosenMethod(0);
        strategy.executeChoosenMethod(1);
    }
}

但我不喜欢Option.Option1.setMethodToExecute(this::action1); 因为我的枚举有越来越多的选择,我想在枚举中拥有所有这些。 什么是完美的是这样的:

public class MyStrategy {
    public void executeChoosenMethod(int i) {
        Option.values()[i].execute();
    }

    private void action1() {
        System.out.println("action1");
    }

    private void action2() {
        System.out.println("action2");
    }

    private enum Option {
        Option1(MyStrategy.this::action1), 
        Option2(MyStrategy.this::action2);

        private InvokeAction methodToExecute;

        private Option(InvokeAction method) {
            methodToExecute = method;
        }

        public void execute() {
            methodToExecute.execute();
        }
    }

    @FunctionalInterface
    private interface InvokeAction {
        void execute();
    }
}

但这是不可能的,因为枚举是静态的,我无法通过MyStrategy.this访问封闭的实例。 我需要枚举,因为我有一组选项,并且使用像values()或valueOf()这样的方法很方便,但我想要的是单行调用而不是增长开关。 你有任何想法如何实现这样的一些或有没有任何解决方法使这个枚举构造函数调用可能Option1(MyStrategy.this::action1)

使用枚举,您可以像这样实现它:

public class MyStrategy {
    public void executeChoosenMethod(int i) {
        Option.values()[i].execute(this);
    }

    private void action1() {
        System.out.println("action1");
    }

    private void action2() {
        System.out.println("action2");
    }

    private enum Option {
        Option1(MyStrategy::action1), 
        Option2(MyStrategy::action2);

        private InvokeAction methodToExecute;

        private Option(InvokeAction method) {
            methodToExecute = method;
        }

        public void execute(MyStrategy s) {
            methodToExecute.execute(s);
        }
    }

    @FunctionalInterface
    private interface InvokeAction {
        void execute(MyStrategy s);
    }
}

这使用lambdas这一事实,您可以对任意实例方法进行方法引用,并通过将实例作为第一个参数传入,在特定实例上调用它们。

你是对的。 枚举不可能实现这一点。 但为什么不用一个好老班:

public class MyStrategy {

    public MyStrategy() {
        buildUp();
    }

    public void executeChoosenMethod(int i) {
        actions.get(i).execute();
    }

    private void action1() {
        System.out.println("action1");
    }

    private void action2() {
        System.out.println("action2");
    }

    private List<InvokeAction> actions = new ArrayList<>();

    private void buildUp() {
        actions.add(this::action1);
        actions.add(this::action2);
    }

    @FunctionalInterface
    private interface InvokeAction {
        void execute();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM