2012-08-28 24 views
11

Command pattern có thể được sử dụng để triển khai Transactional behavior (và Undo).
Nhưng tôi không thể tìm thấy một ví dụ về điều này bằng cách googling. Tôi chỉ có thể tìm thấy một số ví dụ tầm thường của đèn là switched on hoặc off.
Tôi có thể tìm ví dụ mã hóa ở đâu (tốt nhất là ở Java) của hành vi này/được thực hiện bằng cách sử dụng Command Pattern?Ví dụ thế giới thực về việc áp dụng mẫu lệnh

Trả lời

11

Trong một trong những dự án của chúng tôi, chúng tôi có các yêu cầu sau đây:

  1. Tạo một bản ghi trong DB.
  2. Gọi dịch vụ để cập nhật hồ sơ liên quan.
  3. Gọi một dịch vụ khác để đăng nhập vé.

Để thực hiện điều này một cách giao dịch, mỗi thao tác được thực hiện như một lệnh có tác vụ hoàn tác. Ở cuối mỗi bước, lệnh được đẩy lên một ngăn xếp. Nếu hoạt động thất bại ở một số bước, sau đó chúng tôi bật các lệnh từ ngăn xếp và gọi hoàn tác hoạt động trên mỗi lệnh xuất hiện. Hoạt động hoàn tác của từng bước được định nghĩa trong việc thực thi lệnh đó để đảo ngược lệnh command.execute() trước đó.

Hy vọng điều này sẽ hữu ích.

+0

Không chắc chắn tôi làm theo. Giao dịch được rollbacked.Is không bao gồm các hoạt động hoàn tác. Bạn đã thực hiện phần nguyên tử với mẫu lệnh chưa? – Jim

+0

Trong giao dịch cấp cơ sở dữ liệu, mỗi thao tác là một lệnh hoàn tác và thực hiện lại các thao tác. Khi quay trở lại, DBMS sẽ gọi hoạt động hoàn tác để hoàn nguyên các thay đổi được thực hiện cho bản sao của DB mà nó đã giữ. Chúng tôi đang mô phỏng cùng một điều trong một giao dịch phân tán trải dài trên các hệ thống. Điều này có ý nghĩa bây giờ không? – Vikdor

+0

'hoàn nguyên các thay đổi được thực hiện cho bản sao của DB mà nó nắm giữ'. Lệnh này áp dụng trước cho bản sao dữ liệu chứ không phải dữ liệu thực tế? Tôi nghĩ rằng nó được áp dụng trực tiếp cho dữ liệu đó là lý do bạn cần' hoàn tác'. Mô tả của bạn hơi rõ ràng nhưng tôi cần thêm một chút chi tiết ở mức thấp nếu có thể xem ảnh lớn – Jim

2
public final class Ping implements Callable<Boolean> { 

    private final InetAddress peer; 

    public Ping(final InetAddress peer) { 
    this.peer = peer; 
    } 

    public Boolean call() { 
    /* do the ping */ 
    ... 
    } 
} 
... 
final Future<Boolean> result 
    = executorService.submit(new Ping(InetAddress.getByName("google.com"))); 
System.out.println("google.com is " + (result.get() ? "UP" : "DOWN")); 
+5

Ví dụ này là gì? – Jim

+0

@Jim bài viết trên Wikipedia mô tả một cách rõ ràng sau đây ... "* Lớp chủ đề chung, có mục đích chung có thể có phương thức' addTask' công cộng thêm mục công việc vào hàng đợi nội bộ của các tác vụ đang chờ hoàn thành ... Các đối tượng trong hàng đợi là các đối tượng lệnh.Thông thường các đối tượng này thực hiện một giao diện chung như 'java.lang.Runnable' cho phép nhóm thread thực hiện lệnh mặc dù chính lớp bản thảo đã được viết mà không có kiến ​​thức nào của các nhiệm vụ cụ thể mà nó sẽ được sử dụng. * " – oldrinb

+0

@Jim đây là một ví dụ trong Java, ngoại trừ việc sử dụng' Callable' trái với 'Runnable' kết hợp với [' ExecutorService'] (http: // docs. oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html). Một ví dụ tương tự như vậy có thể được nhìn thấy trong cuộc thảo luận về chính bài viết Wikipedia [ở đây] (http://en.wikipedia.org/wiki/Talk%3ACommand_pattern#Python_examples). – oldrinb

1

Mẫu lệnh được sử dụng ở nhiều nơi.

  1. Tất nhiên những gì bạn thấy ở khắp mọi nơi là một ví dụ rất nhỏ về GUI Thực hiện, chuyển mạch. Nó cũng được sử dụng rộng rãi là phát triển game. Với mẫu này, người dùng cũng có thể định cấu hình các nút của mình trên màn hình.
  2. Nó cũng được sử dụng trong Mạng, nếu lệnh phải được chuyển sang đầu kia.
  3. Khi người lập trình muốn lưu trữ tất cả các lệnh được thực thi bởi người dùng, ví dụ: đôi khi một trò chơi cho phép bạn phát lại toàn bộ cấp độ.
  4. Nó được sử dụng để thực hiện gọi lại.

Đây là trang web cung cấp ví dụ về mẫu lệnh được sử dụng để gọi lại. http://www.javaworld.com/article/2077569/core-java/java-tip-68--learn-how-to-implement-the-command-pattern-in-java.html?page=2

  1. Đây là liên kết khác hiển thị mẫu lệnh với cơ sở dữ liệu. Mã này nằm trong C#. http://www.codeproject.com/Articles/154606/Command-Pattern-at-Work-in-a-Database-Application
0

You have to define undo(), redo() operations along with execute() in Command interface itself.

dụ:

interface ChangeI { 
    enum State{ READY, DONE, UNDONE, STUCK } ; 
    State getState() ; 

    void execute() ;  
    void undo() ;  
    void redo() ; 
} 

Xác định một Nhà nước trong lớp ConcreteCommand của bạn. Tùy thuộc vào trạng thái hiện tại sau phương thức execute(), bạn phải quyết định có nên thêm lệnh vào Undo Stack hoặc Redo Stack và đưa ra quyết định tương ứng hay không.

abstract class AbstractChange implements ChangeI { 
    State state = State.READY ; 

    public State getState() { return state ; } 

    public void execute() { 
     assert state == State.READY ; 
     try { doHook() ; state = State.DONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    public void undo() { 
     assert state == State.DONE ; } 
     try { undoHook() ; state = State.UNDONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    public void redo() { 
     assert state == State.UNDONE ; 
     try { redoHook() ; state = State.DONE ; } 
     catch(Failure e) { state = State.STUCK ; } 
     catch(Throwable e) { assert false ; } 
    } 

    protected abstract void doHook() throws Failure ; 

    protected abstract void undoHook() throws Failure ; 

    protected void redoHook() throws Failure { doHook() ;} ; 
} 

Hãy xem bài viết này undo-redo để hiểu rõ hơn.

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