具有内部类的请求 - 响应流的模式

时间:2012-03-08 15:14:25

标签: java design-patterns serialization

我有一个由两个进程组成的应用程序,一个客户端进程带有(基于SWT的)GUI和一个服务器进程。客户端进程非常轻量级,这意味着许多GUI操作必须查询服务器进程或请求某些内容,例如响应用户单击按钮或选择菜单项。这意味着会有很多事件处理程序如下所示:

// Method invoked e.g. in response to the user choosing a menu item
void execute(Event event) {
    // This code is executed on the client, and now we need some info off the server:
    server.execute(new RemoteRequest() {
        public void run() {
            // This code is executed on the server, and we need to update the client 
            // GUI with current progress
            final Result result = doSomeProcessing();
            client.execute(new RemoteRequest() {
                public void run() {
                    // This code is again executed on the client
                    updateUi(result);
                }
            }
        }
    });
}

但是,由于server.execute意味着序列化(它在远程机器上执行),因此如果不使整个类可序列化,则不可能使用此模式(因为RemoteRequest内部类不是静态的(为了清楚起见:Request实现不能要求访问父实例,为了应用它们可能是静态的。)

当然,一种解决方案是为请求和响应创建单独的(可能是静态的内部)类,但这会损害可读性并使得理解执行流程变得更加困难。

我试图找到解决此问题的任何标准模式,但我找不到任何可以解决我对可读性的担忧的问题。

要明确的是,会有很多这些操作,而且操作通常很短。请注意,Future对象在这里并不完全有用,因为在许多情况下,对服务器的一个请求将需要在客户端上执行多项操作(通常是变化的),并且它也不总是返回结果。

理想情况下,我希望能够编写这样的代码:(现在显而易见的伪代码,请忽略详细的明显错误)

String personName = nameField.getText();
async exec on server {
    String personAddress = database.find(personName);
    async exec on client {
        addressField.setText(personAddress);
    }
    Order[] orders = database.searchOrderHistory(personName);
    async exec on client {
        orderListViewer.setInput(orders);
    }
}

现在我想明确一点,底层架构已经就位并运行良好,这个解决方案的原因当然不是上面的例子。我唯一想要的是编写如上所述的代码,而不必为每个进程转换定义静态类。我希望通过给出这个例子,我不会让事情变得复杂......

4 个答案:

答案 0 :(得分:1)

我的偏好是使用Command Pattern和通用的AsynchronousCallbacks。例如,这种方法在GWT中用于与服务器通信。命令是Serializable,AsyncCallback是一个接口。

这些方面的东西:

    // from the client
    server.execute(new GetResultCommand(args), new AsyncCallback<Result>() 
            {
                public void onSuccess(Result result) {
                    updateUi(); // happens on the client
                }
            });

然后,服务器需要接收命令,处理它并使用Result发出适当的响应。

答案 1 :(得分:0)

前几天我遇到了类似的问题。 有一个使用匿名类的解决方案(因此不需要你定义静态内部类),但是这些匿名类是静态的(因此不引用外部对象)。

只需在静态方法中定义匿名类,如下所示:

void execute(Event event) {
    static_execute(server, client, event);
}

// An anonymous class is static if it is defined in a static method. Let's use that.
static void static_execute(final TheServer server, final TheClient client, final Event event) {
    server.execute(new RemoteRequest() {
        public void run() {
            final Result result = doSomeProcessing();
            // See note below!
            client.execute(new RemoteRequest() {
                public void run() {
                    updateUi(result);
                }
            });
        }
    });
}

与使用命名的静态内部类相比,这种方法的主要优点可能是您不必为这些类定义字段和构造函数。

- 考虑一下,对于服务器 - &gt;客户端方向,可能需要再次应用相同的技巧。我将此作为练习留给读者: - )

答案 2 :(得分:0)

FIRST: 没有Pattern,如果我建议,你可以创建一个单独的类来处理所有模式。只需将每个事件生成的Object的实例传递给一个类,并将事件请求委托给其他类。委派将导致更清晰的方法,只需要使用instanceof然后进一步委托。每个活动都可以简洁到一个单独的地方。 与上述方法一起,是的,COMMAND PATTERN绝对是一个记录请求的好选项,但是你为每个提出的请求获得EVENT状态,所以你可以尝试STATE PATTERN,因为它允许一个对象在状态改变时改变它的行为。

答案 3 :(得分:0)

我实际上是通过使用自定义序列化程序创建一个基类来解决这个问题。我仍然希望它最终能用语言解决。