Tôi đang làm việc để bao thanh toán lại các khía cạnh nhất định của một dịch vụ web hiện có. Cách các API dịch vụ được triển khai là bằng cách có một loại "đường ống xử lý", trong đó có các tác vụ được thực hiện theo trình tự. Không có gì đáng ngạc nhiên, các tác vụ sau này có thể cần thông tin được tính toán bởi các tác vụ trước đó và hiện tại cách thức này được thực hiện bằng cách thêm các trường vào lớp "trạng thái đường ống".
Tôi đã suy nghĩ (và hy vọng?) Rằng có một cách tốt hơn để chia sẻ thông tin giữa các bước đường ống hơn là có một đối tượng dữ liệu với hàng triệu trường, một số trong đó có ý nghĩa đối với một số bước xử lý chứ không phải cho các bước khác. Sẽ là một nỗi đau lớn để làm cho lớp này an toàn (tôi không biết liệu nó có khả thi hay không), không có cách nào để lý giải về sự bất biến của nó (và có khả năng là nó không có).
Tôi đã xem qua cuốn sách mẫu thiết kế Gang of Four để tìm cảm hứng, nhưng tôi không cảm thấy như có một giải pháp trong đó (Memento có phần giống với tinh thần, nhưng không hoàn toàn). Tôi cũng đã tìm kiếm trực tuyến, nhưng lần thứ hai bạn tìm kiếm "đường ống" hoặc "quy trình công việc" bạn sẽ bị ngập trong thông tin về các đường dẫn Unix, hoặc các công cụ và khung công việc độc quyền.
Câu hỏi của tôi là - làm thế nào bạn sẽ tiếp cận vấn đề ghi lại trạng thái thực thi của một đường ống xử lý phần mềm, để các tác vụ sau này có thể sử dụng thông tin được tính toán bởi những cái trước đó? Tôi đoán sự khác biệt lớn với các ống Unix là bạn không quan tâm đến đầu ra của nhiệm vụ ngay trước đó.
Theo yêu cầu, một số mã giả để minh họa trường hợp sử dụng của tôi:
Đối tượng "bối cảnh đường ống" có một loạt các trường mà các bước đường ống khác nhau có thể cư trú / đọc:
public class PipelineCtx {
... // fields
public Foo getFoo() { return this.foo; }
public void setFoo(Foo aFoo) { this.foo = aFoo; }
public Bar getBar() { return this.bar; }
public void setBar(Bar aBar) { this.bar = aBar; }
... // more methods
}
Mỗi bước của đường ống cũng là một đối tượng:
public abstract class PipelineStep {
public abstract PipelineCtx doWork(PipelineCtx ctx);
}
public class BarStep extends PipelineStep {
@Override
public PipelineCtx doWork(PipelieCtx ctx) {
// do work based on the stuff in ctx
Bar theBar = ...; // compute it
ctx.setBar(theBar);
return ctx;
}
}
Tương tự như vậy đối với một giả thuyết FooStep
, có thể cần Bar được tính toán bởi BarStep trước nó, cùng với các dữ liệu khác. Và sau đó chúng ta có lệnh gọi API thực sự:
public class BlahOperation extends ProprietaryWebServiceApiBase {
public BlahResponse handle(BlahRequest request) {
PipelineCtx ctx = PipelineCtx.from(request);
// some steps happen here
// ...
BarStep barStep = new BarStep();
barStep.doWork(crx);
// some more steps maybe
// ...
FooStep fooStep = new FooStep();
fooStep.doWork(ctx);
// final steps ...
return BlahResponse.from(ctx);
}
}