design-patterns - 解耦核心和辅助功能的设计模式
问题描述
考虑一个同步(Java)函数WORKER
,它接受一些输入并返回一些输出。我将其称为核心功能。它的确切性质和实施是无关紧要的;然而,重要的是该功能WORKER
是巨大的,它由多个步骤/子步骤/子子步骤组成,并且在计算输出时会启动大型 OOP 机器。
有一些与核心功能正交的辅助功能:WORKER
必须被监控/跟踪和报告(最后的统计数据)。目前,辅助功能嵌入在核心功能中,导致难以维护、繁琐的代码。
问题是:是否有一些设计模式可以解耦核心和辅助功能?
我的第一个想法是WORKER
借助一组可能的状态来定义。达到这些状态中的任何一个都会触发一些注册观察者的回调(通过它解决辅助功能)。这是演示该想法的代码:
public class StateMachine<State> {
protected State state;
public StateMachine(State state) {this.state = state;}
public ArrayList<StateObserver<State>> observers = new ArrayList<>();
public void transit(State newState) {
observers.stream()
.filter(o -> o.from.equals(state) && o.to.equals(newState))
.forEach(o -> o.callback.run());
state = newState;
}
public void registerObserver(State from, State to, Runnable callback) {
observers.add(new StateObserver<State>(from, to, callback));
}
}
@AllArgsConstructor public class StateObserver<State> {
State from, to;
Runnable callback;
}
@Getter public class Worker extends StateMachine<Worker.State> {
enum State { INIT, WORKING, DONE; }
public Worker() { super(State.INIT); }
@SneakyThrows public void doWork() {
for (int i = 0; i < 10; ++i) {
transit(State.WORKING);
Thread.sleep(100);
}
transit(State.DONE);
}
}
public class Progress {
public Progress(Worker worker) {
worker.registerObserver(Worker.State.INIT, Worker.State.WORKING, () -> System.out.print("Starting...\n[ "));
worker.registerObserver(Worker.State.WORKING, Worker.State.WORKING, () -> System.out.print("\b=>"));
worker.registerObserver(Worker.State.WORKING, Worker.State.DONE, () -> System.out.print("\b]\ndone.\n"));
}
}
public class App {
public static void main(String[] args){
Worker worker = new Worker();
new Progress(worker);
worker.doWork();
}
}
但是,此代码有一些严重的限制:
- 目前尚不清楚为 Worker (sub-Workers?) 创建子状态的最佳方法是什么
- 应如何宣传子子状态以供观察员注册
- 观察者如何从 Worker 访问任意中间/临时对象(例如上例中的循环变量
i
)
解决方案
推荐阅读
- android - How @OnLifecycleEvent annotated methods from Architecture Components get hooked up with the LifecycleOwner?
- php - Prestashop 1.6 -> 通过 ajax 更改订单状态,电子邮件错误
- c++ - Qt:未找到 QTableWidget::cellClicked 信号/插槽的问题
- java - jshell(Java 9 shell)集成在 SublimeREPL 中没有响应
- python - 如何在 Python 中使用 BeautifulSoup 在 XML 文件中获取所有具有相同名称的标签?
- chromium-embedded - c# Cefsharp (like chromium) 不在 facebook 上显示视频
- jquery - 标题仅显示几秒钟
- bash - 检查函数返回是否在区间内
- intellij-idea - Run single Kotlin file
- python-3.x - 如何根据另一个数据框中的列值创建布尔列