2012-03-08 23 views
5

Tôi có một ứng dụng bao gồm hai quy trình, một quá trình khách hàng với GUI (dựa trên SWT) và một quy trình máy chủ. Quá trình khách hàng rất nhẹ, có nghĩa là rất nhiều hoạt động GUI sẽ phải truy vấn quá trình máy chủ hoặc yêu cầu nó đến một cái gì đó, ví dụ như để phản hồi người dùng nhấp vào một nút hoặc chọn một mục menu. Điều này có nghĩa rằng sẽ có rất nhiều xử lý sự kiện trông như thế này:Mẫu cho dòng yêu cầu đáp ứng với các lớp bên trong

// 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); 
       } 
      } 
     } 
    }); 
} 

Tuy nhiên, kể từ khi server.execute ngụ ý một serialization (nó được thực hiện trên một máy từ xa), mô hình này là không thể không làm cho toàn bộ lớp serializable (kể từ khi các lớp bên trong RemoteRequest không tĩnh (chỉ cần được rõ ràng: nó không phải là một yêu cầu rằng việc thực hiện Request có thể truy cập vào trường hợp cha mẹ, vì lợi ích của ứng dụng mà họ có thể là tĩnh)

Tất nhiên , một giải pháp là tạo các lớp riêng biệt (có thể là bên trong tĩnh) cho Yêu cầu và Phản hồi, nhưng điều này làm tổn thương khả năng đọc và làm cho nó khó hơn xóa luồng thực hiện.

Tôi đã cố gắng tìm bất kỳ mẫu chuẩn nào để giải quyết vấn đề này, nhưng tôi không tìm thấy bất kỳ điều gì trả lời mối quan tâm của tôi về khả năng đọc.

Để rõ ràng, sẽ có rất nhiều hoạt động này và hoạt động thường khá ngắn. Lưu ý rằng các đối tượng Future không hoàn toàn hữu ích ở đây, vì trong nhiều trường hợp, một yêu cầu tới máy chủ sẽ cần phải thực hiện nhiều thứ trên máy khách (thường thay đổi) và nó cũng không phải lúc nào cũng được trả về.

Lý tưởng nhất, tôi muốn để có thể viết mã như thế này: (rõ ràng pseudo-code bây giờ, xin vui lòng bỏ qua các lỗi rõ ràng trong chi tiết)

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); 
    } 
} 

Bây giờ tôi muốn được rõ ràng, rằng tiềm ẩn kiến trúc được đặt ra và hoạt động tốt, lý do giải pháp này là có tất nhiên không phải là ví dụ trên. Điều duy nhất tôi đang tìm kiếm là một cách để viết mã như trên, mà không cần phải định nghĩa các lớp tĩnh cho mỗi quá trình chuyển đổi. Tôi hy vọng rằng tôi không chỉ làm phức tạp mọi thứ bằng cách đưa ra ví dụ này ...

+0

Điều này liên quan đến jms như thế nào? Mã này có được thực thi trên máy khách hoặc máy chủ hoặc máy khác không? – Andrejs

+0

Vâng, đúng thế. Có những trường hợp mã được thực hiện trên máy khách và trên máy chủ. Ngoài ra còn có những trường hợp máy khách thực hiện một cái gì đó trên máy chủ mà lần lượt thực hiện một cái gì đó trên máy khách. – Krumelur

+0

Tôi nghĩ chúng ta cần thêm một chút chi tiết. Yêu cầu/đáp ứng các lớp học của riêng bạn hoặc chúng là một phần của một số khuôn khổ? Chính xác những gì thực hiện không? – Andrejs

Trả lời

0

Tôi thực sự đã kết thúc việc giải quyết điều này bằng cách tạo một lớp cơ sở với một bộ nối tiếp tùy chỉnh để xử lý việc này. Tôi vẫn hy vọng nó được giải quyết bằng ngôn ngữ cuối cùng.

1

Sở thích của tôi là sử dụng Command Pattern và AsynchronousCallbacks chung. Cách tiếp cận này được sử dụng trong GWT để giao tiếp với máy chủ, ví dụ. Các lệnh là Serializable, AsyncCallback là một giao diện.

cái gì đó dọc những dòng này:

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

Máy chủ sau đó cần phải nhận được một lệnh, xử lý nó và đưa ra một phản ứng thích hợp với kết quả.

+0

Trong trường hợp này, sẽ 'AsyncCallback' không phải là một lớp bên trong không tĩnh? Làm thế nào nó được serialized đến máy chủ mà không yêu cầu lớp ngoài được serialized? – Krumelur

+0

AsyncCallback sẽ không cần phải được tuần tự hóa và gửi đi. Đối tượng 'server' chỉ giữ một tham chiếu đến nó và sau đó gọi nó khi đối tượng Result đến từ máy chủ thực. Chỉ có Command và Result cần được Serializable. – Andrejs

+0

Bạn có một điểm tốt, mặc dù vấn đề của tôi là tôi đã muốn 'GetResultCommand' trở thành một lớp ẩn danh, và 'AsyncCallback' không quan trọng đối với tôi (mặc dù nó sẽ tốt đẹp). – Krumelur

0

Tôi đã gặp sự cố tương tự vào ngày khác. Có một giải pháp sử dụng các lớp ẩn danh (và do đó không yêu cầu bạn định nghĩa các lớp bên trong tĩnh), nhưng làm cho các lớp ẩn danh đó tĩnh (và do đó không tham chiếu đến đối tượng bên ngoài).

Đơn giản chỉ cần xác định các lớp vô danh trong một phương pháp tĩnh, như thế này:

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); 
       } 
      }); 
     } 
    }); 
} 

Ưu điểm chính của phương pháp này, so với sử dụng tên lớp bên trong tĩnh, có lẽ rằng bạn tránh được việc phải xác định các lĩnh vực và nhà thầu cho những lớp đó.

- Hãy suy nghĩ về điều đó, cùng một mẹo có thể cần phải được áp dụng một lần nữa, cho hướng máy chủ-> khách hàng. Tôi sẽ để điều này như một bài tập cho người đọc :-)

+0

Cảm ơn bạn đã đề cập đến điều này. Tôi coi là một giải pháp như thế này, nhưng hóa ra mã này trở nên phức tạp hơn trong trường hợp của tôi, được viết theo cách này. – Krumelur

0

FIRST: Nếu không có mẫu, nếu tôi đề nghị, bạn có thể tạo một lớp riêng để xử lý tất cả các mẫu. Chỉ cần vượt qua thể hiện của từng sự kiện được tạo đối tượng cho một lớp và ủy quyền yêu cầu sự kiện cho các lớp khác. Đoàn sẽ dẫn đến cách tiếp cận rất rõ ràng hơn, chỉ cần sử dụng instanceof và sau đó ủy quyền thêm. Mỗi sự kiện có thể ngắn gọn đến một nơi riêng biệt. Cùng với phương pháp trên, có, COMMAND PATTERN chắc chắn là một lựa chọn tốt để đăng nhập yêu cầu nhưng bạn đang nhận được EVENT State cho mọi yêu cầu được nêu ra, vì vậy bạn có thể thử STATE PATTERN vì nó cho phép một đối tượng thay đổi hành vi của nó khi thay đổi trạng thái.

Các vấn đề liên quan