Bạn gặp khó khăn vì bạn đang sử dụng mẫu sai.
Task
s không được trả về trạng thái tiếp theo. Bạn nên sử dụng ma trận State
để kiểm soát luồng. Bằng cách này, luồng của bạn không bị rối loạn bên trong các nhiệm vụ và các State
s vẫn còn riêng tư cho hệ thống luồng.
Nếu bạn muốn Task
để kiểm soát luồng, chúng sẽ trả lại thứ gì đó (có thể thành công/thất bại) để tác động đến bộ điều khiển luồng. Họ không được xác định trạng thái tiếp theo, họ phải ảnh hưởng đến trạng thái tiếp theo.
Added
Dưới đây là một ví dụ hơi giả tạo của những gì tôi có ý nghĩa. Chú ý cách Task
s được gắn vào mỗi State
và luồng được điều khiển bởi một Map
chỉ đơn thuần giữ mỗi chuyển đổi trạng thái.
Tôi đã thực hiện một nỗ lực mã thông báo để phù hợp với kết quả trả về của bạn, nhưng tôi nghi ngờ rằng chỉ cần làm quá tải các vấn đề và một khi bạn nắm lấy sự tách biệt dòng chảy, bạn sẽ nhận ra những gì tôi đang cố giải thích.
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);
}
}
}
Added
Đơn giản hóa này bằng cách loại bỏ yêu cầu của bạn để kiểm soát dòng chảy thông qua các kết quả của các phương pháp nhiệm vụ chúng tôi nhận:
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);
}
}
}
đó, tôi nghĩ rằng, chứng tỏ việc tách kiểm soát dòng chảy từ thực hiện nhiệm vụ mà tôi đã cố gắng vượt qua.
Không, bạn không thể đánh dấu một số hằng số enum công khai và một số gói riêng tư. –
Trong trường hợp này có thể bạn có thể sử dụng các enums java cũ, chỉ là một lớp với một số hằng số tĩnh cuối cùng. – Marcelo
Trong thực tế, bạn không thể đánh dấu chúng bất cứ điều gì. Họ là 'công khai' và đó là nó. –