【问题标题】:Real world example of application of the command pattern命令模式应用的真实世界示例
【发布时间】:2012-08-22 15:11:59
【问题描述】:

Command pattern 可用于实现Transactional behavior(和Undo)。
但我无法通过谷歌搜索找到这些示例。我只能找到switched onoff 的灯的一些琐碎示例。
我在哪里可以找到使用Command Pattern 实现的这种/这些行为的编码示例(最好在Java 中)?

【问题讨论】:

  • 搜索RunnableCallable的任何用法。

标签: java oop design-patterns transactions command-pattern


【解决方案1】:

在我们的一个项目中,我们有以下要求:

  1. 在 DB 中创建记录。
  2. 调用服务来更新相关记录。
  3. 调用另一个服务来记录工单。

为了以事务方式执行此操作,每个操作都作为带有撤消操作的命令来实现。在每一步结束时,命令被压入堆栈。如果操作在某个步骤失败,则我们从堆栈中弹出命令,并对弹出的每个命令调用撤消操作。每个步骤的撤消操作都在该命令实现中定义,以反转之前的 command.execute()。

希望这会有所帮助。

【讨论】:

  • 不确定我是否遵循。事务已回滚。不是由撤消操作组成。您是如何使用命令模式实现原子部分的?
  • 在数据库级事务中,每个操作都是一个带有撤消和重做操作的命令。回滚时,DBMS 将调用撤消操作来恢复对其持有的数据库副本所做的更改。我们在跨系统的分布式事务中模拟同样的事情。这现在有意义吗?
  • revert the changes made to the copy of the DB it held。所以该命令首先应用于数据的副本而不是实际数据?我认为它直接应用于数据,这就是您需要undo的原因。您的描述有点清楚,但如果可能的话,我需要更多的低级细节才能看到全局
  • 不,DBMS 将复制数据,以便其他人无需您的更改即可看到数据(事务隔离级别仅与此有关)。当您提交时,副本将更新到实际位置,以便其他人可以看到您的更改。命令的重做操作在故障恢复期间与检查点一起使用(DBMS 概念值得一读)
  • 那么在您的实施示例中,您复制了哪些数据部分来模拟事务行为?整个数据?
【解决方案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"));

【讨论】:

  • @Jim 关于该模式的维基百科文章明确提到了以下内容...“一个典型的通用线程池类可能有一个公共 addTask 方法,该方法将工作项添加到等待完成的任务的内部队列......队列中的项目是命令对象。通常这些对象实现一个公共接口,例如java.lang.Runnable,即使线程池类本身也允许线程池执行命令是在不知道将使用它的具体任务的情况下编写的。"
  • @Jim 这是 Java 中的一个例子,除了使用 Callable 而不是 RunnableExecutorService 结合使用。类似的例子可以在关于维基百科文章本身here的讨论中看到。
  • 但我要的是该模式的具体应用示例。尽管您提供了该模式的一般示例
  • @Jim 通常任何Runnable 都会满足命令模式。例如class ExitTask implements Runnable { public void run() { System.exit(0); } }
  • 也许我误读了您的答案,但我在 OP 中的问题是,如何使用命令模式(带有 Java 示例)来实现事务行为。
【解决方案3】:

命令模式用在很多地方。

  1. 当然,随处可见的是一个非常简单的 GUI 实现示例,即开关。它也被广泛用于游戏开发。使用这种模式,用户也可以在屏幕上配置他的按钮。
  2. 如果必须将命令传递到另一端,它也可用于网络。
  3. 当程序员想要存储用户执行的所有命令时,例如有时一个游戏可以让你重播整个关卡。
  4. 用于实现回调。

这是一个提供用于回调的命令模式示例的站点。 http://www.javaworld.com/article/2077569/core-java/java-tip-68--learn-how-to-implement-the-command-pattern-in-java.html?page=2

  1. 这是另一个链接,它显示了带有数据库的命令模式。代码在 C# 中。 http://www.codeproject.com/Articles/154606/Command-Pattern-at-Work-in-a-Database-Application

【讨论】:

    【解决方案4】:

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

    示例:

    interface ChangeI {
        enum State{ READY, DONE, UNDONE, STUCK } ;
        State getState() ;
    
        void execute() ;    
        void undo() ;    
        void redo() ;
    }
    

    ConcreteCommand 类中定义一个状态。根据execute() 方法后的当前状态,您必须决定是否应将命令添加到Undo StackRedo Stack 并做出相应的决定。

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

    请查看此undo-redo 命令文章以获得更好的理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 2016-11-26
      • 1970-01-01
      • 2011-03-22
      • 2012-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多