【问题标题】:How to migrate a java command pattern using runnable to PHP 7.4?如何使用 runnable 将 java 命令模式迁移到 PHP 7.4?
【发布时间】:2020-06-20 20:47:21
【问题描述】:

出于学习目的,我正在尝试将此 Java 命令模式示例迁移到 PHP:

https://codereview.stackexchange.com/questions/52110/command-pattern-implementation

As @simon commented,使用方法引用运算符,会使代码现代化不少:

class MyCommand implements Order {
    private final Runnable action;

    public MyCommand(Runnable action) {
         this.action = action;
    }

    @Override
    public void execute() {
         action.run();
    }
}

然后你可以创建这样的命令:

MyCommand bsc = new MyCommand(stock::buy);
MyCommand ssc = new MyCommand(stock::sell);

我当前的 PHP 实现在这里:https://3v4l.org/iIHn9

那么在 PHP 中实现 MyCommand 类的最佳方法是什么?

【问题讨论】:

    标签: java php runnable porting command-pattern


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      在 PHP 中,您可以使用类似于 Java 中的方法引用的call_user_func 来实现相同的目的。

      <?php
      
      namespace StockCommandNS;
      
      //Command interface
      interface Order {
          public function execute();
      }
      
      //Receiver class
      class StockTrade {
      
          public function buy() {
              print("You want to buy stocks\n");
          }
      
          public function sell() {
              print("You want to sell stocks\n");
          }
      }
      
      //Invoker class
      class Agent {
      
          public function placeOrder(Order $order) {
              $order->execute($order);
          }
      }
      
      //ConcreteCommand Class
      class GenericOrder implements Order {
      
          private $action;
      
          public function __construct($action) {
              $this->action = $action;
          }
      
          public function execute() {
              call_user_func($this->action);
          }
      }
      
      $stock = new StockTrade();
      $bsc = new GenericOrder([$stock, 'buy']);
      $ssc = new GenericOrder([$stock, 'sell']);
      $agent = new Agent();
      $agent->placeOrder($bsc); // Buy Shares
      $agent->placeOrder($ssc); // Sell Shares
      

      7.2.0 - 7.4.3 的输出

      You want to buy stocks
      You want to sell stocks
      

      运行 PHP 代码:https://3v4l.org/fWo20

      另一个不太干净的选择是使用变量函数。

      class GenericOrder implements Order {
      
          private $stock;
          private $action;
      
          public function __construct($stock, $action) {
              $this->stock = $stock;
              $this->action = $action;
          }
      
          public function execute() {
              $method = $this->action;
              $this->stock->$method();
          }
      }
      
      $bsc = new GenericOrder($stock, 'buy');
      $ssc = new GenericOrder($stock, 'sell');
      

      我不确定使用方法引用的方法是否在所有情况下都更好。 根据经验,您应该始终根据每个用例考虑何时使用方法引用或匿名函数是命令模式。

      【讨论】:

        【解决方案3】:

        正如 Evgeniy 已经提到的,您可以使用 call_user_func()

        由于有很多方法可以解决此问题,因此我已将我的解决方案添加到您的问题中。您还可以通过在类中添加__invoke 方法来创建对象callable。也可以返回 callable 函数。我总共添加了 3 个示例。

        这是我在 java 中的 MyCommand 类的版本,用于所有 3 个示例。

        class MyCommand implements Order
        {
            private $action;
        
            public function __construct(callable $action)
            {
                $this->action = $action;
            }
        
            public function execute()
            {
                // Option 1) use call_user_function
                call_user_func($this->action);
        
                // Option 2) define it as a variable and call it by adding `()`
                //$action = $this->action;
                //$action();
            }
        }
        

        示例 1) 可调用函数 (https://3v4l.org/FVTEK)

        class Stock
        {
            public function buy(): callable
            {
                return function () {
                    echo "You want to buy stocks via callable function" . PHP_EOL;
                };
            }
        
            public function sell(): callable
            {
                return function () {
                    echo "You want to sell stocks via callable function" . PHP_EOL;
                };
            }
        }
        
        $stock = new Stock();
        $bsc = new MyCommand($stock->buy());
        $ssc = new MyCommand($stock->sell());
        
        $bsc->execute();
        $ssc->execute();
        

        示例 2) 可调用类 (https://3v4l.org/BrKjv)

        class StockBuy
        {
            public function __invoke()
            {
                echo "You want to buy stocks via __invoke()" . PHP_EOL;
            }
        }
        
        class StockSell
        {
            public function __invoke()
            {
                echo "You want to sell stocks __invoke()" . PHP_EOL;
            }
        }
        
        $bsc = new MyCommand(new StockBuy());
        $ssc = new MyCommand(new StockSell());
        
        $bsc->execute();
        $ssc->execute();
        

        示例 3) 返回可调用的静态成员函数。只是一个更接近java的例子 (https://3v4l.org/PKk4B)

        class Stock
        {
            static public function buy(): callable
            {
                return function () {
                    echo "You want to buy stocks via callable function" . PHP_EOL;
                };
        
                // or as callable object
                // return new StockBuy();
            }
        
            static public function sell(): callable
            {
                return function () {
                    echo "You want to sell stocks via callable function" . PHP_EOL;
                };
        
                // or as callable object
                // return new StockSell();
            }
        }
        
        $bsc = new MyCommand(Stock::buy());
        $ssc = new MyCommand(Stock::sell());
        $bsc->execute();
        $ssc->execute();
        

        如果您还有其他问题,请告诉我。

        【讨论】:

          猜你喜欢
          • 2018-06-07
          • 1970-01-01
          • 1970-01-01
          • 2016-09-24
          • 1970-01-01
          • 2015-02-04
          • 2023-03-15
          • 1970-01-01
          • 2021-02-14
          相关资源
          最近更新 更多