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

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

以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;    }

 

posted @   一束光  阅读(392)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用

友情链接

CFC4N
点击右上角即可分享
微信分享提示