首頁  >  問答  >  主體

利用多態性同時傳回多個結果和使用多種行為的方法

<p>我正在使用 Laravel 9 並且我有一個請求可以包含:</p> <ul> <li>名為 SEASON 的參數,值可以是 <code>array</code> 或 null 所以 <code>SEASON</code> 參數可以是 <code>array</code> 也可以是 <code>null</code></li> <li>名稱為 EXPIRY 的參數可以是 <code>array</code> 也可以是 <code>null</code></li> </ul> <p>我有兩個類,一個用於<code>SEASON</code> 功能,另一個用於<code>EXPIRY</code> ,它們都從<code>Repository</code>擴展。兩者都有一個名為 <code>execute</code> 的方法,該方法傳回一個陣列</p> <pre class="brush:php;toolbar:false;">abstract class Repository { abstract public function execute(): array; } class Expiry extends Repository { public function execute() { return ['The Request contain Expiry Parameter, and seasonal behaviours is done']; } } class Season extends Repository { public function execute() { return ['The Request contain Season Parameter, and expiry behaviours is done']; } }</pre> <p>如果我的請求包含SEASON,我想呼叫Season類別的execute方法,或者如果我的請求包含Expiry,我想要呼叫expiry的execute方法。或者調用它們並將執行的執行返回合併到一個數組中,以便我可以得到結果。 </p> <pre class="brush:php;toolbar:false;">['The Request contain Expiry Parameter, and seasonal behaviours is done', 'The Request contain Expiry Parameter, and expiry behaviours is done'] Request contain Expiry Parameter, and expiry behaviours is done']>/pre&> ; <p>這就是我在控制器中嘗試過的:</p> <pre class="brush:php;toolbar:false;">public function bootstrap($data) { $parseTopics = Helper::parseTopicsRequest(); $basicProgram = new BasicProgramRepository(); $seasonalProgram = new SeasonalProgramRepository($parseTopics['SEASONAL']); $object = count($parseTopics['SEASONAL']) ? $seasonalProgram : $basicProgram; // Polymorphism return $object->execute(); }</pre> <p>問題1: 我不確定我是否應該使用這種方式或類似的方式來解決我的需求:</p> <pre class="brush:php;toolbar:false;">$employe = new Program(new BasicProgramRepository());</pre> <p>預期結果: 預期結果取決於我是否有季節參數和到期時間。我想要實現的是使用不同的行為(execute方法)</p>
P粉187677012P粉187677012380 天前526

全部回覆(1)我來回復

  • P粉086993788

    P粉0869937882023-09-06 18:46:06

    如果你想實作多型方法,最好建立儲存庫或僅用於管理該邏輯的東西。

    這是範例。

    class SampleRepository
    {
        /**
         * repository instance value
         *
         * @var string[] | null
         */
        private $sampleArray; // maybe here is SEASON or EXPIRY or null
    
        /**
         * constructor
         *
         * @param string[] | null $sampleArray
         */
        public function __construct($sampleArray)
        {
            $this->sampleArray = $sampleArray;
        }
    
        /**
         * execute like class interface role
         *
         * @return array
         */
        public function execute()
        {
            return (!$this->sampleArray) ? [] : $this->getResult();
        }
    
        /**
         * get result
         *
         * @return array
         */
        private function getResult()
        {
            // maybe pattern will be better to manage another class or trait.
            $pattern = [
                "SEASON" => new Season(),
                "EXPIRY" => new Expiry()
            ];
            return collect($this->sampleArray)->map(function($itemKey){
                $requestClass = data_get($pattern,$itemKey);
                if (!$requestClass){ // here is space you don't expect class or canIt find correct class
                    return ["something wrong"];
                }
                return $requestClass->execute();
            })->flatten();
        }
    }

    你可以這樣呼叫。

    $sampleRepository  = new SampleRepository($sampleValue); // expect string[] or null like ["SEASON"],["SEASON","EXPIRY"],null
        $result = $sampleRepository->execute(); // [string] or [string,string] or []

    此方法僅適用於您的參數指定值。 如果Season類別和Expiry類別的回傳結果幾乎相同,那麼最好在trait上進行管理。 (即範例程式碼中的 $pattern)

    嘗試一些。

    我讀了評論,所以關注..

    例如,它更願意只取得 getResult() 的結果。 因此,某些模式和如此多的邏輯不應該寫在 getResult() 上;

    如果您使用特徵,這是一個範例。 首先,您需要建立管理行為類別。

    行為.php

    <?php 
    namespace App\Repositories;
    
    class Behavior
    {
        use Behavior\BehaviorTrait;
        // if you need to add another pattern, you can add trait here.
    }

    然後,您需要在同級位置建立Behavior目錄。 你移動該目錄,你就創建了這樣的特徵檔。

    <?php
    
    namespace App\Repositories\Behavior;
    
    trait BehaviorTrait
    {
        public static function findAccessibleClass(string $itemKey)
        {
          return data_get([
            "SEASON" => new Season(),
            "EXPIRY" => new Expiry()
          ],$itemKey);
        }
    }

    findAccessibleClass() 方法負責找出正確的類別。

    然後,你可以像這樣呼叫這個方法。

    private function getResult()
        {
            return collect($this->sampleArray)->map(function($itemKey){
                $requestClass = Behavior::findAccessibleClass($itemKey); // fix here.
                if (!$requestClass){ // here is space you don't expect class or canIt find correct class
                    return ["something wrong"];
                }
                return $requestClass->execute();
            })->flatten();
        }

    如果 getResult() 中的程式碼太多,最好將負責的程式碼分開。

    要建立Behavior Trait,getResult不需要負責行為邏輯。簡而言之,它將很容易測試或修復。

    希望一切順利。

    回覆
    0
  • 取消回覆