工厂函数与工厂类的区别与联系
两则都是提供生成某个对象的包装。什么时候运用类,而什么时候运用方法,一般没有固定的标准。一般来说,如果这个包装函数包含的功能比较多的话,可以把他封装成一个类,把里面各个功能模块提取出来写成单独的类方法,这样,调用的时候先生成类,然后再调用生成对象的包装方法。反之,如果一个包装函数的内容很少,可以用函数生成。
以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 ; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 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 构建精确任务处理应用