工厂函数与工厂类的区别与联系

两则都是提供生成某个对象的包装。什么时候运用类,而什么时候运用方法,一般没有固定的标准。一般来说,如果这个包装函数包含的功能比较多的话,可以把他封装成一个类,把里面各个功能模块提取出来写成单独的类方法,这样,调用的时候先生成类,然后再调用生成对象的包装方法。反之,如果一个包装函数的内容很少,可以用函数生成。

以Yii中的CWidgetFactory为例:

在工厂类中,我们可以自定义$enableSkin的值及init()处理程序

class CWidgetFactory extends CApplicationComponent implements IWidgetFactory { /** * @var boolean whether to enable widget skinning. Defaults to false. * @see skinnableWidgets * @since 1.1.3 */ public $enableSkin=false; /** * @var array widget initial property values. Each array key-value pair * represents the initial property values for a single widget class, with * the array key being the widget class name, and array value being the initial * property value array. For example, * <pre> * array( * 'CLinkPager'=>array( * 'maxButtonCount'=>5, * 'cssFile'=>false, * ), * 'CJuiDatePicker'=>array( * 'language'=>'ru', * ), * ) * </pre> * * Note that the initial values specified here may be overridden by * the values given in {@link CBaseController::createWidget} calls. * They may also be overridden by widget skins, if {@link enableSkin} is true. * @since 1.1.3 */ public $widgets=array(); /** * @var array list of widget class names that can be skinned. * Because skinning widgets has performance impact, you may want to specify this property * to limit skinning only to specific widgets. Any widgets that are not in this list * will not be skinned. Defaults to null, meaning all widgets can be skinned. * @since 1.1.3 */ public $skinnableWidgets; /** * @var string the directory containing all the skin files. Defaults to null, * meaning using the "skins" directory under the current application's {@link CWebApplication::viewPath}. */ public $skinPath; private $_skins=array(); // class name, skin name, property name => value /** * Initializes the application component. * This method overrides the parent implementation by resolving the skin path. */ public function init() { parent::init(); if($this->enableSkin && $this->skinPath===null) $this->skinPath=Yii::app()->getViewPath().DIRECTORY_SEPARATOR.'skins'; } /** * Creates a new widget based on the given class name and initial properties. * @param CBaseController $owner the owner of the new widget * @param string $className the class name of the widget. This can also be a path alias (e.g. system.web.widgets.COutputCache) * @param array $properties the initial property values (name=>value) of the widget. * @return CWidget the newly created widget whose properties have been initialized with the given values. */ public function createWidget($owner,$className,$properties=array()) //包装函数,这个包装函数因为需要获得对应$skin的文件,所以把这快代码封装起来 getSkin { $className=Yii::import($className,true); $widget=new $className($owner); if(isset($this->widgets[$className])) $properties=$properties===array() ? $this->widgets[$className] : CMap::mergeArray($this->widgets[$className],$properties); if($this->enableSkin) { if($this->skinnableWidgets===null || in_array($className,$this->skinnableWidgets)) { $skinName=isset($properties['skin']) ? $properties['skin'] : 'default'; if($skinName!==false && ($skin=$this->getSkin($className,$skinName))!==array()) $properties=$properties===array() ? $skin : CMap::mergeArray($skin,$properties); } } foreach($properties as $name=>$value) $widget->$name=$value; return $widget; } /** * Returns the skin for the specified widget class and skin name. * @param string $className the widget class name * @param string $skinName the widget skin name * @return array the skin (name=>value) for the widget */ protected function getSkin($className,$skinName) { if(!isset($this->_skins[$className][$skinName])) { $skinFile=$this->skinPath.DIRECTORY_SEPARATOR.$className.'.php'; if(is_file($skinFile)) $this->_skins[$className]=require($skinFile); else $this->_skins[$className]=array(); if(($theme=Yii::app()->getTheme())!==null) { $skinFile=$theme->getSkinPath().DIRECTORY_SEPARATOR.$className.'.php'; if(is_file($skinFile)) { $skins=require($skinFile); foreach($skins as $name=>$skin) $this->_skins[$className][$name]=$skin; } } if(!isset($this->_skins[$className][$skinName])) $this->_skins[$className][$skinName]=array(); } return $this->_skins[$className][$skinName]; } }

调用:
    public function createWidget($className,$properties=array())
    {
        $widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
        $widget->init();
        return $widget;
    }
原文地址:https://www.cnblogs.com/Alight/p/3116684.html