漫談設計模式之工廠模式

今天在這裏不過多介紹什麼是設計模式和爲什麼要使用它?可以參考漫談設計模式之組合模式

一、什麼是抽象工廠設計模式?

    一言以蔽之,抽象工廠就是用來創建功能相關的類,

二、在什麼場景下使用它?

    顧名思義,在我們的業務當中會有一種場景,有一個查詢頁面,上面有很多很多的查詢條件,最終你會組合這些查詢條件查詢出實際想要的數據,請問你是怎麼做的?下面是我的設計,運用了單例、工廠和策略模式,一切面向接口編程。

三、設計思路

1、定義策略接口,定義一個format方法

2、按實際業務抽象出三種策略,1、模糊查詢,2、等於查詢,3、要經過特殊處理的查詢

3、定義一個抽象工廠,按需初始化三種策略對象

4、定義一個統一入口TutorConditionFormatter,創建工廠對象,工廠對象創建策略對象,策略對象處理數據,最後返回要求格式

5、業務當中直接調用TutorConditionFormatter


<?php
//------策略模式
/**
 * 策略模式interface
 * TutorConditionFormatterInterface
 */

namespace Logic\Tutor\ConditionFactoryFormatter;


interface TutorConditionFormatterInterface
{
    public function format($aTutor);
}

<?php
/**
 * 模糊查詢策略
 * TutorConditionLikeFormatter
 */

namespace Logic\Tutor\ConditionFactoryFormatter;


class TutorConditionLikeFormatter implements TutorConditionFormatterInterface
{
    public function format ($aParams)
    {
        $aFormatColumn  = ['certifications','background','interview_time'];

        $aParamKey      = array_keys($aParams);
        $aFormatKey     = array_intersect($aFormatColumn,$aParamKey);

        $aCondition     = [];
        if ($aFormatKey) {
            foreach ($aFormatKey as $column) {
                $item   = $aParams["$column"];
                if (!empty($item)) {
                    $item   = array_unique($item);
                    sort($item);
                    $aCondition[]   = sprintf("%s like '%s'",$column,'%'.implode(",", $item).'%');
                }
            }
        }

        return $aCondition;
    }
}


<?php
/**
 * 特殊查詢策略
 * TutorConditionSpecialFormatter
 */

namespace Logic\Tutor\ConditionFactoryFormatter;


class TutorConditionSpecialFormatter implements TutorConditionFormatterInterface
{
    const HAVE_RESUME           = 1;//已上傳簡歷
    const NONE_RESUME           = 2;//未上傳簡歷

    public function format ($aParams)
    {

        $aCondition     = [];
        if (isset($aParams['nationality']) && !empty($aParams['nationality'])) {
            //對於others,查詢非United States和Canada的集合
            if ($aParams['nationality'] > 2) {
                $aCondition[] = sprintf('nationality >=3');
            } else {
                $aCondition[] = sprintf("nationality = %d",$aParams['nationality']);
            }
        }

        if (isset($aParams['resume']) && !empty($aParams['resume'])) {
            if (self::HAVE_RESUME == $aParams['resume']) {
                $aCondition[]   = sprintf("resume <> ''");
            } elseif (self::NONE_RESUME == $aParams['resume']) {
                $aCondition[]   = sprintf("resume = ''");
            }
        }

        if (isset($aParams['sourcing_team']) && !empty($aParams['sourcing_team'])) {
            if (is_array($aParams['sourcing_team'])) {
                $aCondition[]   = sprintf("sourcing_team in('%s')",implode("','", $aParams['sourcing_team']));
            } else {
                $aCondition[]   = sprintf("sourcing_team = %s",$aParams['sourcing_team']);
            }
        }

        if (isset($aParams['demo_time_start']) && !empty($aParams['demo_time_start'])) {
            $aCondition[]       = sprintf("demo_result_date >= '%s 00:00:00'",$aParams['demo_time_start']);
        }
        if (isset($aParams['demo_time_end']) && !empty($aParams['demo_time_end'])) {
            $aCondition[]       = sprintf("demo_result_date <= '%s 23:59:59'",$aParams['demo_time_end']);
        }

        return $aCondition;
    }
}


<?php
/**
 * 相等查詢策略
 * TutorConditionEqualFormatter
 */

namespace Logic\Tutor\ConditionFactoryFormatter;


class TutorConditionEqualFormatter implements TutorConditionFormatterInterface
{
    const STATUS_FAILED = 'failed';
    public function format ($aParams)
    {
        $aFormatColumn  = ['mobile','country','state','email','time_zone','teaching_experience','zoom_id',
            'interviewer','demo_status','sa_signed','skype_id','self_applied','source','educational_attainment'
        ];

        $aParamKey      = array_keys($aParams);
        $aFormatKey     = array_intersect($aFormatColumn,$aParamKey);

        $aCondition     = [];
        if ($aFormatKey) {
            foreach ($aFormatKey as $column) {
                $item   = $aParams["$column"];
                if (!empty($item)) {
                    $aCondition[]  = sprintf("%s = '%s'",$column,$item);
                }
            }
        }

        return $aCondition;
    }
}


//------抽象工廠
<?php
/**
 * 查詢條件格式化工廠
 * TutorConditionFactory
 */

namespace Logic\Tutor\ConditionFactoryFormatter;

class TutorConditionFactory
{
    private $_oFactory          = null;
    public static $_instance    = null;

    /**
     * TutorConditionFactory constructor.
     */
    private function __construct ()
    {
        if($this->_oFactory == null) {
            $this->register();
        }
    }

    /**
     * @return TutorConditionFactory|null
     */
    public static function getInstance()
    {
        if (self::$_instance == null) {
            self::$_instance = new TutorConditionFactory();
        }
        return self::$_instance;
    }

    /**
     * 註冊工廠類
     * @return $this
     */
    public function register()
    {
        $this->_oFactory['equal']           = __NAMESPACE__ . '\TutorConditionEqualFormatter';
        $this->_oFactory['like']            = __NAMESPACE__ . '\TutorConditionLikeFormatter';
        $this->_oFactory['special']         = __NAMESPACE__ . '\TutorConditionSpecialFormatter';
        return $this;
    }

    /**
     * 創建工廠類
     * @param $type
     * @return mixed
     * @throws \Exception
     */
    public function create($type)
    {
        if (!array_key_exists($type,$this->_oFactory)) {
            throw new \Exception(sprintf("%s is not valid",$type));
        }

        $producer   = $this->_oFactory["$type"];
        return new $producer();
    }
}


<?php
/**
 * 格式化數據統一入口,完成兩件事
 * 按要求生產策略對象
 * 按策略對象格式化處理數據,最終返回所需的數據格式
 */

namespace Logic\Tutor;
use \Logic\Tutor\ConditionFactoryFormatter;

class TutorConditionFormatter
{
    public function __construct ()
    {
        //定義需要處理的策略
        $this->_aFormatter  = ['equal','like','special'];
    }

    public function format($aParams)
    {
        $oFactory       = ConditionFactoryFormatter\TutorConditionFactory::getInstance();

        //刪除p和psize,與tutor無關
        unset($aParams['p'],$aParams['psize']);

        $aCondition[]   = sprintf("training_type_id >=1");
        if (empty($aParams)) {
            return $aCondition;
        }
        
        //根據要求的策略處理數據,返回要求的數據
        foreach ($this->_aFormatter as $formatter)
        {
            $oProducer  = $oFactory->create($formatter);
            $item       = $oProducer->format($aParams);
            $aCondition = array_merge($aCondition,$item);
        }
        unset($formatter,$item,$aParams);

        return array_unique($aCondition);
    }
}


//業務當中具體使用
<?php

//工廠模式格式化查詢條件
$oConditionFormatter    = new TutorConditionFormatter();
/**
 * $aSearch 是接受的請求參數
 * $aCondition 是最終處理好的可供DbModel直接使用的查詢條件數據
 */
$aCondition             = $oConditionFormatter->format($aSearch);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章