잘못된 패턴을 사용하고있어 어려움을 겪고 있습니다.
Task
은 다음 상태를 반환하지 않아야합니다. 흐름을 제어하려면 State
의 행렬을 사용해야합니다. 이렇게하면 작업 내에서 작업 흐름이 엉망이되지 않고 State
이 흐름 시스템에 비공개로 유지됩니다.
Task
에서 흐름을 제어하려면 흐름 컨트롤러에 영향을주기 위해 무언가 (아마도 성공/실패)를 반환해야합니다. 그들은 가 다음 상태를 정의하면 안되며, 은 다음 상태가되어야합니다.
추가
여기에 무슨 뜻인지의 약간 인위적인 예입니다. 각 State
에 Task
이 붙어 있고 흐름은 각 상태 전이를 보유하는 Map
에 의해 제어됩니다.
반환 결과와 일치하는 토큰을 만들었지 만 문제가 지나치게 복잡하다는 의심을 품고 일단 상태에서 흐름을 분리하면 내가 설명하려고하는 것을 깨닫게됩니다.
public class Test {
public void test() {
new Thread(new Engine()).start();
}
static final Map<State, State> flow = new HashMap<>();
static {
flow.put(State.Start, State.A);
flow.put(State.A, State.B);
flow.put(State.B, State.Finished);
}
public static class Engine implements Runnable {
State state = State.Start;
@Override
public void run() {
while (state != State.Finished) {
System.out.println("State: "+state);
// Perform all tasks of this state.
for (Task task : state.tasks) {
System.out.println("Task: "+task);
Result result = Result.Start;
// Keep performing until completed.
while (result != Result.Completed) {
System.out.println("Result: "+result);
result = result.perform(task);
}
System.out.println("Result: "+result);
}
// All tasks performed! Next state.
state = flow.get(state);
}
System.out.println("State: "+state);
}
}
enum State {
Start,
A(Task.One, Task.Two),
B(Task.Two),
Finished;
Iterable<Task> tasks;
State(Task... tasks) {
this.tasks = Arrays.asList(tasks);
}
}
enum Result {
Start {
@Override
Result perform(Task t) {
return t.initialise();
}
},
Executing {
@Override
Result perform(Task t) {
return t.execute();
}
},
Finalising {
@Override
Result perform(Task t) {
return t.finalise();
}
},
Completed {
@Override
Result perform(Task t) {
// Stop there.
return Completed;
}
};
abstract Result perform(Task t);
}
enum Task {
One {
@Override
Result initialise() {
return Result.Executing;
}
@Override
Result execute() {
return Result.Finalising;
}
@Override
Result finalise() {
return Result.Completed;
}
},
Two {
@Override
Result initialise() {
return Result.Executing;
}
@Override
Result execute() {
return Result.Finalising;
}
@Override
Result finalise() {
return Result.Completed;
}
};
abstract Result initialise();
abstract Result execute();
abstract Result finalise();
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
추가
작업 방법의 결과를 통해 흐름을 제어하기 위해 귀하의 요구 사항을 제거하여이 단순화 우리가 얻을 :의 분리를 보여, 내 생각,
public class Test {
public void test() {
new Thread(new Engine()).start();
}
static final Map<State, State> flow = new HashMap<>();
static {
flow.put(State.Start, State.A);
flow.put(State.A, State.B);
flow.put(State.B, State.Finished);
}
public static class Engine implements Runnable {
State state = State.Start;
@Override
public void run() {
while (state != State.Finished) {
System.out.println("State: "+state);
// Perform all tasks of this state.
for (Task task : state.tasks) {
System.out.println("Task: "+task);
task.initialise();
task.execute();
task.finalise();
}
// All tasks performed! Next state.
state = flow.get(state);
}
System.out.println("State: "+state);
}
}
enum State {
Start,
A(Task.One, Task.Two),
B(Task.Two),
Finished;
Iterable<Task> tasks;
State(Task... tasks) {
this.tasks = Arrays.asList(tasks);
}
}
enum Task {
One {
@Override
void execute() {
}
},
Two {
@Override
void execute() {
}
};
// Nothing by default.
void initialise() {
}
abstract void execute();
// Nothing by default.
void finalise() {
}
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
작업 실행에서 흐름 제어를 시도했습니다.
아니요, 일부 열거 형 상수 및 일부 패키지 전용을 표시 할 수 없습니다. –
이 경우 어쩌면 몇 가지 최종 정적 상수와 그냥 이전 자바 enums, 클래스를 사용할 수 있습니다. – Marcelo
사실, 아무 것도 표시 할 수 없습니다. 그들은 '공개'이며 그게 전부입니다. –