带有内部枚举的策略模式
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)
?
你是对的。这对于枚举是不可能的。但为什么不使用旧的 class:
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();
}
}
使用枚举,您可以像这样实现它:
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 的事实,您可以对任意实例方法进行方法引用,并通过将实例作为第一个参数传入来在特定实例上调用它们。
我正试图从我的代码中删除大的 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)
?
你是对的。这对于枚举是不可能的。但为什么不使用旧的 class:
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();
}
}
使用枚举,您可以像这样实现它:
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 的事实,您可以对任意实例方法进行方法引用,并通过将实例作为第一个参数传入来在特定实例上调用它们。