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