6

Từ Examples of GoF Design Patterns in Java's core libraries câu hỏi, nó đã được trích dẫn rằngVí dụ về mẫu lệnh java với lớp Runnable: Bộ nhận có bị thiếu không?

Tất cả các triển khai của java.lang.Runnable là ví dụ về lệnh mẫu.

Theo sự hiểu biết của tôi về mẫu Command,

Khách hàng gọi Invoker =>Invoker gọi ConcreteCommand =>ConcreteCommand cuộc gọi Receiver phương pháp, mà thực hiện trừu tượng Lệnh phương thức.

Có một cái nhìn tại example

mẫu Command sơ đồ UML làm việc này từ this article được hiển thị như dưới đây.

enter image description here

Có một cái nhìn tại mã này:

public class ThreadCommand{ 
    public static void main(String args[]){ 
     Thread t = new Thread(new MyRunnable()); 
     t.start(); 
    } 
} 
class MyRunnable implements Runnable{ 
    public void run(){ 
     System.out.println("Running:"+Thread.currentThread().getName()); 
    } 
} 
  1. ThreadCommandKhách hàng
  2. Runnable giao diện là lệnh
  3. MyRunnableConcreteCommmand
  4. Chủ đềInvoker với start() phương pháp gọi ConcreteCommand implementaiton (trong đó kêu gọi run() phương pháp)

là Receiver thiếu ở đây? Hay MyRunnable có thể đóng vai trò kết hợp của ConcreteCommand và Receiver?

Trả lời

3

Người nhận là một di tích của C/C++, trong đó phương pháp này được gọi là tách ra khỏi đối tượng để gọi nó về. Bạn có thể thực hiện hành vi đó trong Java bằng cách truyền một phương thức bằng cách sử dụng sự phản chiếu; nhưng như bạn đã đoán, cách tiếp cận Java thành ngữ hơn là xử lý lệnh và người nhận cụ thể như một đối tượng.

+0

Đối tượng * người nhận * là loại đại diện cho logic nghiệp vụ của ứng dụng. Trách nhiệm của một lệnh không phải là sở hữu logic nghiệp vụ, nhưng để lộ logic nghiệp vụ này cho các máy khách bằng cách sử dụng một giao diện chung và tiêu chuẩn, tức là phương thức 'execute'. Sau đó, tôi nghĩ rằng người nhận không chỉ đơn thuần là di tích của C/C++. –

0

Sẽ không nhận được ...

System.out.println("Running:"+Thread.currentThread().getName()); 

cuộc gọi trong method run. Bởi vì đó là nhận được hành động để làm khi Runnable chạy.

1

Một câu trả lời đã được đăng ở đây và đã bị tác giả xóa ngay lập tức. Trong khi đọc câu trả lời, tôi đã tìm ra giải pháp.

Tôi chỉ có thể chuyển đổi ví dụ trên sang biểu đồ UML mẫu Command với một thay đổi nhỏ.

Tôi có thể chuyển đối tượng người nhận cho MyRunnable (ConcreteCommand).

Bây giờ tôi đã thay đổi mã của mình như dưới đây.

public class ThreadCommand{ 
    public static void main(String args[]){ 
     Receiver r = new AC(); 
     Thread t = new Thread(new MyRunnable(r)); 
     t.start(); 
    } 
} 
class MyRunnable implements Runnable{ 
    private Receiver receiver; 
    public MyRunnable(Receiver r){ 
     this.receiver = r; 
    } 
    public void run(){ 
     receiver.execute(); 
    } 
} 
interface Receiver{ 
    public void execute(); 
} 
class AC implements Receiver{ 
    public void execute(){ 
     System.out.println("I am AC"); 
    } 
} 
class Fan implements Receiver{ 
    public void execute(){ 
     System.out.println("I am Fan"); 
    } 
} 

Output:

java ThreadCommand 
I am AC 
0

Tôi muốn cung cấp cho hai xu của tôi ...

Các mẫu Command gốc tách Command đối tượng từ Receiver đối tượng vì trách nhiệm của hai bộ khác nhau.

Receiver s sở hữu logic nghiệp vụ của ứng dụng. Các loại này sẽ tồn tại bên ngoài mẫu. Trong một trường hợp thực tế, Receiver có thể đã có mặt trong cơ sở mã, trước các lệnh.

Ví dụ, suy nghĩ cho một ngân hàng ứng dụng , một máy thu có thể được đại diện bởi các loại sau đây:

public class Account { 
    private final double balance; 
    // Construct omissis 
    public Account deposit(double amount) { 
     // Deposit code 
    } 
    public Account withdraw(double amount) { 
     // Withdraw code 
    } 
} 

Một trong những mục tiêu của các mẫu thiết kế lệnh là của cho một thống nhất, cách đồng nhất và tiêu chuẩn để thực hiện các thao tác trên một tập hợp các đối tượng (tức là người nhận). Họ không phải quan tâm cách thực hiện logic kinh doanh thực sự. Điều này sẽ giới hạn khả năng sử dụng lại của mã triển khai logic nghiệp vụ.

Vì lý do này, triển khai Command s phải chuyển tiếp thông tin đến Receiver. Nó theo một ví dụ.

public class DepositCommand implements Command { 
    private final Account account; 
    // An instance of Command should reprenset only a single request 
    private final double amount; 
    public DepositCommand(Account account, double amount) { 
     this.account = account; 
     this.amount = amount; 
    } 

    public void execute() { 
     account.deposit(amount); 
    } 

    // Omissis.. 
} 

Kết luận, hiển thị trong câu trả lời được chấp nhận là không chính xác.

Người nhận là một di tích của C/C++ trong đó phương thức được gọi được tách ra khỏi đối tượng để gọi nó.