jQuery技术内幕:深入解析jQuery架构设计与实现原理. 2.7 原型属性和方法

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

2.7 原型属性和方法

在构造jQuery对象模块时,除了2.3节和2.6节已经介绍和分析的jQuery.fn.init()和jQuery.fn.extend()外,还定义了一些其他的原型属性和方法,其整体源码结构如代码清单2-2所示。

代码清单2-2  原型属性和方法

97 jQuery.fn = jQuery.prototype = {

98     constructor: jQuery,

99     init: function( selector, context, rootjQuery ) {}

210     selector: "",

213     jquery: "1.7.1",

216     length: 0,

219     size: function() {},

223     toArray: function() {},

229     get: function( num ) {},

241     pushStack: function( elems, name, selector ) {},

270     each: function( callback, args ) {},

274     ready: function( fn ) {}, //

284     eq: function( i ) {},

291     first: function() {},

295     last: function() {},

299     slice: function() {},

304     map: function( callback ) {},

310     end: function() {},

316     push: push,

317     sort: [].sort,

318     splice: [].splice

319 };

其中.ready()用于绑定ready事件,将在9.11节进行介绍和分析。下面对其他的原型属性和方法逐一介绍和分析。

2.7.1 .selector、.jquery、.length、.size()

属性selector用于记录jQuery查找和过滤DOM元素时的选择器表达式,但不一定是可执行的选择器表达式,该属性更多的是为了方便调试。下面是一些示例:

$('div').find('p').selector            // "div p"

$('div p').selector                        // "div p"

$('div').first().selector                         // "div.slice(0,1)"

属性jquery表示正在使用的jQuery版本号。

属性.length表示当前jQuery对象中元素的个数。

方法.size()返回当前jQuery对象中元素的个数。方法.size()在功能上等价于属性.length,但应该优先使用属性.length,因为它没有函数调用开销。

属性.selector、.jquery、.length、.size()的相关代码如下所示:

209     // Start with an empty selector

210     selector: "",

211

212     // The current version of jQuery being used

213     jquery: "1.7.1",

214

215     // The default length of a jQuery object is 0

216     length: 0,

217

218     // The number of elements contained in the matched element set

219     size: function() {

220         return this.length;

221     },

222

2.7.2 .toArray()、.get( [index] )

1.?.toArray()

方法.toArray()将当前jQuery对象转换为真正的数组,转换后的数组包含了所有元素。方法.toArray()的实现巧妙地借用了数组的方法slice(),相关的代码如下所示:

86     // Save a reference to some core methods

87     toString = Object.prototype.toString,

88     hasOwn = Object.prototype.hasOwnProperty,

89     push = Array.prototype.push,

90     slice = Array.prototype.slice,

91     trim = String.prototype.trim,

92     indexOf = Array.prototype.indexOf,

 

223    toArray: function() {

224       return slice.call( this, 0 );

225    },

第86~92行:连同slice()一起声明的还有toString()、hasOwn()、trim()、indexOf(),这里通过声明对这些核心方法的引用,使得在jQuery代码中可以借用这些核心方法的功能,执行时可通过方法call()和apply()指定方法执行的环境,即关键字this所引用的对象。这种“借鸡下蛋”的技巧非常值得借鉴。

数组方法slice()返回数组的一部分,语法如下:

array.slice(start, end)

// 参数start 表示数组片段开始处的下标。如果是负数,它声明从数组末尾开始算起的位置

// 参数end 表示数组片段结束处的后一个元素的下标。如果没有指定这个参数,切分的数组包含从 start 开始到数组结束的所有元素。如果这个参数是负数,它声明的是从数组尾部开始算起的元素

2.?.get( [index] )

方法.get( [index] )返回当前jQuery对象中指定位置的元素或包含了全部元素的数组。如果没有传入参数,则调用.toArray()返回包含了所有元素的数组;如果指定了参数index,则返回一个单独的元素;参数index从0开始计算,并且支持负数,负数表示从元素集合末尾开始计算。相关代码如下所示:

227     // Get the Nth element in the matched element set OR

228     // Get the whole matched element set as a clean array

229     get: function( num ) {

230         return num == null ?

231

232             // Return a 'clean' array

233             this.toArray() :

234

235             // Return just the object

236             ( num < 0 ? this[ this.length + num ] : this[ num ] );

237     },

第236行:先判断num是否小于0,如果小于0,则用length + num重新计算下标,然后使用数组访问操作符([])获取指定位置的元素,这是支持下标为负数的一个小技巧;如果num大于等于0,则直接返回指定位置的元素。

2.7.3 .each( function(index, Element) )、jQuery.each( collection, callback (indexInArray, valueOfElement) )

1.?.each( function(index, Element) )

方法.each()遍历当前jQuery对象,并在每个元素上执行回调函数。每当回调函数执行时,会传递当前循环次数作为参数,循环次数从0开始计数;更重要的是,回调函数是在当前元素为上下文的语境中触发的,即关键字this总是指向当前元素;在回调函数中返回false可以终止遍历。

方法.each()内部通过简单的调用静态方法jQuery.each()实现,相关代码如下所示:

267     // Execute a callback for every element in the matched set.

268     // (You can seed the arguments with an array of args, but this is

269     // only used internally.)

270     each: function( callback, args ) {

271         return jQuery.each( this, callback, args );

272     },

2.?jQuery.each( collection, callback(indexInArray, valueOfElement) )

静态方法jQuery.each()是一个通用的遍历迭代方法,用于无缝地遍历对象和数组。对于数组和含有length属性的类数组对象(如函数参数对象arguments),该方法通过下标遍历,从0到length-1;对于其他对象则通过属性名遍历(for-in)。在遍历过程中,如果回调函数返回false,则结束遍历。相关代码如下所示:

627     // args is for internal usage only

628     each: function( object, callback, args ) {

629         var name, i = 0,

630             length = object.length,

631             isObj = length === undefined || jQuery.isFunction( object );

632

633         if ( args ) {

634             if ( isObj ) {

635                 for ( name in object ) {

636                     if ( callback.apply( object[ name ], args ) === false ) {

637                         break;

638                     }

639                 }

640             } else {

641                 for ( ; i < length; ) {

642                     if ( callback.apply( object[ i++ ], args ) === false ) {

643                         break;

644                     }

645                 }

646             }

647

648         // A special, fast, case for the most common use of each

649         } else {

650             if ( isObj ) {

651                 for ( name in object ) {

652                     if ( callback.call( object[ name ], name, object[ name ] ) === false ) {

653                         break;

654                     }

655                 }

656             } else {

657                 for ( ; i < length; ) {

658                     if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {

659                         break;

660                     }

661                 }

662             }

663         }

664

665         return object;

666     },

第628行:定义方法jQuery.each( object, callback, args ),它接受3个参数。

参数object:待遍历的对象或数组。

参数callback:回调函数,会在数组的每个元素或对象的每个属性上执行。

参数args:传给回调函数callback的参数数组,可选。如果没有传入参数args,则执行回调函数时会传入两个参数(下标或属性名,对应的元素或属性值)如果传入了参数args,则只把该参数传给回调函数。

第631行:变量isObj表示参数object是对象还是数组,以便决定遍历方式。如果object.length是undefined或object是函数,则认为object是对象,设置变量isObj为true,将通过属性名遍历;否则认为是数组或类数组对象,设置变量isObj为false,将通过下标遍历。

第633~646行:如果传入了参数args,对于对象,通过for-in循环遍历属性名,对于数组或类数组对象,则通过for循环遍历下标,执行回调函数时只传入一个参数args。

注意,执行回调函数callback时通过方法apply()指定this关键字所引用的对象,同时要求并假设参数args是数组,如果不是就会抛出TypeError。

第648~663行:如果未传入参数args,对于对象,通过for-in循环遍历属性名,对于数组或类数组对象,则通过for循环遍历下标,执行回调函数时传入两个参数:下标或属性名,对应的元素或属性值。

注意,执行回调函数callback时通过方法call()指定this关键字所引用的对象。

似乎jQuery.each()的代码略显啰嗦,因为第633~646行和第648~663行的代码相似度很高,只是触发回调函数的方式和参数不同,完全可以考虑把它们合并,在合并后的代码中根据变量isObj的值决定触发方式和参数,这样就可以减少一半的代码,但是,这也会导致在遍历过程中需要反复判断变量isObj的值。两权相较,方法jQuery.each()选择了“略显啰嗦的”代码来避免性能下降。

第665行:最后,返回传入的参数object。方法.each()调用jQuery.each()时,把当前jQuery对象作为参数object传入,这里返回该参数,以支持链式语法。

2.7.4 .map( callback(index, domElement) )、jQuery.map( arrayOrObject, callback(value, indexOrKey) )

1.?.map( callback(index, domElement) )

方法.map()遍历当前jQuery对象,在每个元素上执行回调函数,并将回调函数的返回值放入一个新jQuery对象中。该方法常用于获取或设置DOM元素集合的值。

执行回调函数时,关键字this指向当前元素。回调函数可以返回一个独立的数据项或数据项数组,返回值将被插入结果集中;如果返回一个数组,数组中的元素会被插入结果集;如果回调函数返回null或undefined,则不会插入任何元素。

方法.map()内部通过静态方法jQuery.map()和原型方法.pushStack()实现,相关代码如下所示:

304     map: function( callback ) {

305         return this.pushStack( jQuery.map(this, function( elem, i ) {

306             return callback.call( elem, i, elem );

307         }));

308     },

原型方法.pushStack()将在2.7.5节介绍和分析。

2.?jQuery.map( arrayOrObject, callback(value, indexOrKey) )

静态方法jQuery.map()对数组中的每个元素或对象的每个属性调用一个回调函数,并将回调函数的返回值放入一个新的数组中。执行回调函数时传入两个参数:数组元素或属性值,元素下标或属性名。关键字this指向全局对象window。回调函数的返回值会被放入新的数组中;如果返回一个数组,数组中将被扁平化后插入结果集;如果返回null或undefined,则不会放入任何元素。相关代码如下所示:

760     // arg is for internal usage only

761     map: function( elems, callback, arg ) {

762         var value, key, ret = [],

763             i = 0,

764             length = elems.length,

765             // jquery objects are treated as arrays

766             isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

767

768         // Go through the array, translating each of the items to their

769         if ( isArray ) {

770             for ( ; i < length; i++ ) {

771                 value = callback( elems[ i ], i, arg );

772

773                 if ( value != null ) {

774                     ret[ ret.length ] = value;

775                 }

776             }

777

778         // Go through every key on the object,

779         } else {

780             for ( key in elems ) {

781                 value = callback( elems[ key ], key, arg );

782

783                 if ( value != null ) {

784                     ret[ ret.length ] = value;

785                 }

786             }

787         }

788

789         // Fl atten any nested arrays

790         return ret.concat.apply( [], ret );

791     },

第761行:定义方法jQuery.map( elems, callback, arg ),它接受3个参数:

参数elems:待遍历的数组或对象。

参数callback:回调函数,会在数组的每个元素或对象的每个属性上执行。执行时传入两个参数:数组元素或属性值,元素下标或属性名。

参数arg:仅限于jQuery内部使用。如果调用jQuery.map()时传入了参数arg,则该参数会被传给回调函数callback。

第766行:变量isArray表示参数elems是否是数组,以便决定遍历方式。如果为true,将通过下标遍历;否则将通过属性名遍历。这行复合布尔表达式有些长,为了方便分析,将这行代码等价地格式化为下面的形式:

isArray = elems instanceof jQuery

   || length !== undefined && typeof length === "number"

       && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] )

              || length === 0

              || jQuery.isArray( elems ) ) ;

如果elems是jQuery对象,则变量isArray为true;如果elem.length是数值型,且满足以下条件之一,则变量isArray为true:

length大于0,且elems[0]存在,且elems[ length -1 ]存在,即elems是一个类数组对象。

length等于0。

elems是真正的数组。

第769~776行:对于数组或类数组对象,则通过for循环遍历下标,为每个元素执行回调函数callback,执行时依次传入三个参数:元素、下标、arg。如果回调函数的返回值不是null和undefined,则把返回值放入结果集ret。

第778~787行:对于对象,则通过for-in循环遍历属性名,为每个属性值执行回调函数callback,执行时依次传入三个参数:属性值、属性名、arg。如果回调函数的返回值不是null和undefined,则把返回值放入结果集ret。

第790行:最后在空数组[]上调用方法concat()扁平化结果集ret中的元素,并返回。

2.7.5 .pushStack( elements, name, arguments )

原型方法.pushStack()创建一个新的空jQuery对象,然后把DOM元素集合放入这个jQuery对象中,并保留对当前jQuery对象的引用。

原型方法.pushStack()是核心方法之一,它为以下方法提供支持:

jQuery对象遍历:.eq()、.first()、.last()、.slice()、.map()。

DOM查找、过滤:.find()、.not()、.filter()、.closest()、.add()、.andSelf()。

DOM遍历:.parent()、.parents()、.parentsUntil()、.next()、.prev()、.nextAll()、.prevAll()、

.nextUnit()、.prevUnit()、.siblings()、.children()、.contents()。

DOM插入:jQuery.before()、jQuery.after()、jQuery.replaceWith()、.append()、.prepent()、

.before()、.after()、.replaceWith()。

相关代码如下所示:

239     // Take an array of elements and push it onto the stack

240     // (returning the new matched element set)

241     pushStack: function( elems, name, selector ) {

242         // Build a new jQuery matched element set

243         var ret = this.constructor();

244

245         if ( jQuery.isArray( elems ) ) {

246             push.apply( ret, elems );

247

248         } else {

249             jQuery.merge( ret, elems );

250         }

251

252         // Add the old object onto the stack (as a reference)

253         ret.prevObject = this;

254

255         ret.context = this.context;

256

257         if ( name === "find" ) {

258             ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;

259         } else if ( name ) {

260             ret.selector = this.selector + "." + name + "(" + selector + ")";

261         }

262

263         // Return the newly-formed element set

264         return ret;

265     },

第241行:定义方法.push( elems, name, selector ),它接受3个参数:

参数elems:将放入新jQuery对象的元素数组(或类数组对象)。

参数name:产生元素数组elems的jQuery方法名。

参数selector:传给jQuery方法的参数,用于修正原型属性.selector。

第243行:构造一个新的空jQuery对象ret,this.constructor指向构造函数jQuery()。

第245~250行:把参数elems合并到新jQuery对象ret中。如果参数elems是数组,则借用数组方法push()插入,否则调用方法jQuery.merge( first, second )合并。

第253行:在新Query对象ret上设置属性prevObject,指向当前jQuery对象,从而形成一个链式栈。因此,方法.pushStack()的行为还可以理解为,构建一个新的jQuery对象并入栈,新对象位于栈顶,这也是该方法如此命名的原因所在。

第255行:在新jQuery对象ret上设置属性prevObject,指向当前jQuery对象的上下文,后续的jQuery方法可能会用到这个属性。

第257~261行:在新jQuery对象ret上设置属性selector,该属性不一定是合法的选择器表达式,更多的是为了方便调试,例如,下面的代码打印了调用方法.pushStack()之后属性selector的值:

console.log( $('div').eq(0).selector );

// div.slice(0,1)

 

console.log( $('div').first().selector );

// div.slice(0,1)

 

console.log( $('div').last().selector );

// div.slice(-1)

 

console.log( $('div').slice(0,9).selector );

// div.slice(0,9)

 

console.log( $('div').find('p').selector );

// div p

 

console.log( $('div').not('.cls').selector );

// div.not(.cls)

 

console.log( $('div').find('p').not('.cls').selector );

// div p.not(.cls)

第264行:最后返回新jQuery对象ret。

2.7.6 .end()

方法.end()结束当前链条中最近的筛选操作,并将匹配元素集合还原为之前的状态。相关代码如下所示:

310     end: function() {

311         return this.prevObject || this.constructor(null);

312     },

第311行:返回前一个jQuery对象。如果属性prevObject不存在,则构建一个空的jQuery对象返回。

方法.pushStack()用于入栈,方法.end()则用于出栈。这两个方法可以像下面的例子这样使用:

$('ul.first').find('.foo')

   .css('background-color', 'red')

.end().find('.bar')

   .css('background-color', 'green')

.end();

2.7.7 .eq( index )、.first()、.last()、.slice( start [, end] )

方法.eq( index )将匹配元素集合缩减为集合中指定位置的元素;方法.first()将匹配元素集合缩减为集合中的第一个元素;方法.last()将匹配元素集合缩减为集合中的最后一个元素;方法.slice( start [, end] )将匹配元素集合缩减为指定范围的子集。

方法.first()和.last()通过调用.eq( index )实现,.eq( index )则通过.slice( start [, end] )实现,.slice( start [, end] )则通过调用.pushStack( elements, name, arguments )实现,方法调用链为.first/last()→.eq( index )→.slice( start [, end] )→.pushStack( elements, name, arguments )。相关代码如下所示:

284      eq: function( i ) {

285         i = +i;

286         return i === -1 ?

287             this.slice( i ) :

288             this.slice( i, i + 1 );

289      },

290

291      first: function() {

292         return this.eq( 0 );

293      },

294

295      last: function() {

296         return this.eq( -1 );

297      },

298

299      slice: function() {

300         return this.pushStack( slice.apply( this, arguments ),

301             "slice", slice.call(arguments).join(",") );

302     },

第285行:如果参数i是字符串,则通过在前面加上一个加号把该参数转换为数值。

第300~301行:先借用数组方法slice()从当前jQuery对象中获取指定范围的子集(数组),再调用方法.pushStack()把子集转换为jQuery对象,同时通过属性prevObject保留了对当前jQuery对象的引用。

2.7.8 .push( value, ... )、.sort( [orderfunc] )、.splice( start,deleteCount, value, ... )

方法.push( value, ... )向当前jQuery对象的末尾添加新元素,并返回新长度,例如:

var foo = $(document);

foo.push( document.body ); // 2

方法.sort( [orderfunc] )对当前jQuery对象中的元素进行排序,可以传入一个比较函数来指定排序方式,例如。

var foo = $([33, 4, 1111, 222]);

foo.sort(); // [1111, 222, 33, 4]

foo.sort(function(a, b){

   console.log( 'orderfun', a, b );

   return a - b;

}) // [4, 33, 222, 1111]

方法.splice( start,deleteCount, value, ... )向当前jQuery对象中插入、删除或替换元素。如果从当前jQuery对象中删除了元素,则返回含有被删除元素的数组。例如:

var foo = $('<div id="d1" /><div id="d2" /><div id="d3" />');

// [<div id="d1"></div>, <div id="d2"></div>, <div id="d3"></div>]

foo.splice( 1, 2 );

// [<div id="d2"></div>, <div id="d3"></div>]

方法.push()、.sort()、.splice()仅在内部使用,都指向同名的数组方法,因此它们的参数、功能和返回值与数组方法完全一致。相关代码如下所示:

314     // For internal use only.

315     // Behaves like an Array's method, not like a jQuery method.

316     push: push,

317     sort: [].sort,

318     splice: [].splice

319 };

2.7.9 小结

构造jQuery对象模块的原型属性和方法可以总结为图2-8。

相关文章
|
20天前
|
机器学习/深度学习 安全 算法
十大主流联邦学习框架:技术特性、架构分析与对比研究
联邦学习(FL)是保障数据隐私的分布式模型训练关键技术。业界开发了多种开源和商业框架,如TensorFlow Federated、PySyft、NVFlare、FATE、Flower等,支持模型训练、数据安全、通信协议等功能。这些框架在灵活性、易用性、安全性和扩展性方面各有特色,适用于不同应用场景。选择合适的框架需综合考虑开源与商业、数据分区支持、安全性、易用性和技术生态集成等因素。联邦学习已在医疗、金融等领域广泛应用,选择适配具体需求的框架对实现最优模型性能至关重要。
286 79
十大主流联邦学习框架:技术特性、架构分析与对比研究
|
16天前
|
机器学习/深度学习 缓存 自然语言处理
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构
DeepSeekMoE是一种创新的大规模语言模型架构,融合了专家混合系统(MoE)、多头潜在注意力机制(MLA)和RMSNorm归一化。通过专家共享、动态路由和潜在变量缓存技术,DeepSeekMoE在保持性能的同时,将计算开销降低了40%,显著提升了训练和推理效率。该模型在语言建模、机器翻译和长文本处理等任务中表现出色,具备广泛的应用前景,特别是在计算资源受限的场景下。
340 29
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构
|
14天前
|
机器学习/深度学习 算法 文件存储
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
47 10
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
|
9天前
|
机器学习/深度学习 算法 文件存储
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
20 4
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
|
7天前
|
存储 人工智能 并行计算
2025年阿里云弹性裸金属服务器架构解析与资源配置方案
🚀 核心特性与技术创新:提供100%物理机性能输出,支持NVIDIA A100/V100 GPU直通,无虚拟化层损耗。网络与存储优化,400万PPS吞吐量,ESSD云盘IOPS达100万,RDMA延迟<5μs。全球部署覆盖华北、华东、华南及海外节点,支持跨地域负载均衡。典型应用场景包括AI训练、科学计算等,支持分布式训练和并行计算框架。弹性裸金属服务器+OSS存储+高速网络综合部署,满足高性能计算需求。
|
22天前
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
74 18
|
25天前
|
存储 缓存 关系型数据库
社交软件红包技术解密(六):微信红包系统的存储层架构演进实践
微信红包本质是小额资金在用户帐户流转,有发、抢、拆三大步骤。在这个过程中对事务有高要求,所以订单最终要基于传统的RDBMS,这方面是它的强项,最终订单的存储使用互联网行业最通用的MySQL数据库。支持事务、成熟稳定,我们的团队在MySQL上有长期技术积累。但是传统数据库的扩展性有局限,需要通过架构解决。
65 18
|
10天前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
133 2
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多