漫谈设计模式之工厂模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漫谈设计模式之工厂模式相关的知识,希望对你有一定的参考价值。

今天在这里不过多介绍什么是设计模式和为什么要使用它?可以参考漫谈设计模式之组合模式

一、什么是抽象工厂设计模式?

    一言以蔽之,抽象工厂就是用来创建功能相关的类,

二、在什么场景下使用它?

    顾名思义,在我们的业务当中会有一种场景,有一个查询页面,上面有很多很多的查询条件,最终你会组合这些查询条件查询出实际想要的数据,请问你是怎么做的?下面是我的设计,运用了单例、工厂和策略模式,一切面向接口编程。

三、设计思路

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


本文出自 “我相信” 博客,请务必保留此出处http://mrcelite.blog.51cto.com/2977858/1932030

以上是关于漫谈设计模式之工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式漫谈之二

PHP面向对象之选择工厂和更新工厂

设计模式漫谈之状态模式

设计模式漫谈之解释器模式

设计模式之单例模式

设计模式漫谈之备忘录模式