方法鏈

方法鏈(Method Chaining),也被稱為命名參數法,是在面向對象的程式語言中調用的調用多個方法的通用語法。每一個方法返回一個對象,在一個單一的聲明里,方法鏈省去了中間變數的需要。

簡介

方法鏈(method chaining)是面向對象的程式語言中的一種常見語法,可以讓開發者在只引用對象一次的情況下,對同一個對象進行多次方法調用。

舉個例子:

假設我們有一個Foo類,其中包含有兩個方法——bar和baz。

我們創建一個Foo類的實例:

1 foo = Foo()

如果不使用方法鏈,要想連續調用對象foo的bar和baz方法的話,我們得這樣做:

1 2 foo.bar() # Call method bar() on object foo. foo.baz() # Call method baz() on object foo.

如果使用方法鏈的話,我們就能這樣實現: foo.bar().baz()

方法鏈的優勢

方法鏈的一個好處,是可以減少你使用對象名的次數。調用的方法越多,能夠減少的次數就越多。因此,這個方法也能一定程度上減少需要閱讀、測試、調試、維護的代碼數量。這個好處不大,但也是有用的。

1. 讓調用過程更接近自然語言。
2. 把原本參數列表複雜的方法化作多個參數列表簡單的方法來使用。
3. 減少不必要的代碼量。

這個三點都是有益於開發的,所以方法鏈的存在很有意義。

請注意,方法鏈的一個限制是,只能用在不需要返回其他值的方法上,因為你需要返回self對象。即使Python支持用一個return語句返回多個值,也可能無法解決這個問題。

Python中方法鏈的套用

下面是在Python中實現方法鏈的一個示例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Person: def name(self, value): self.name = value return self def age(self, value): self.age = value return self def introduce(self): print "Hello, my name is", self.name, "and I am", self.age, "years old." person = Person() person.name("EarlGrey").age(21).introduce() # => Hello, my name is EarlGrey and I am 21 years old.

上面那種實現可能太簡單了。更加現實的方法鏈使用方法:編寫一個字元串處理程式string_processor.py,支持方法鏈。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import copy class StringProcessor(object): ''' A class to process strings in various ways. ''' def __init__(self, st): '''Pass a string for st''' self._st = st def lowercase(self): '''Make lowercase''' self._st = self._st.lower() return self def uppercase(self): '''Make uppercase''' self._st = self._st.upper() return self def capitalize(self): '''Make first char capital (if letter); make other letters lower''' self._st = self._st.capitalize() return self def delspace(self): '''Delete spaces''' self._st = self._st.replace(' ', '') return self def rep(self): '''Like Python's repr''' return self._st def dup(self): '''Duplicate the object''' return copy.deepcopy(self) def process_string(s): print sp = StringProcessor(s) print 'Original:', sp.rep() print 'After uppercase:', sp.dup().uppercase().rep() print 'After lowercase:', sp.dup().lowercase().rep() print 'After uppercase then capitalize:', sp.dup().uppercase().\ capitalize().rep() print 'After delspace:', sp.dup().delspace().rep() def main(): print "Demo of method chaining in Python:" # Use extra spaces between words to show effect of delspace. process_string('hOWz It GoInG?') process_string('The QUIck brOWn fOx') main()

下面是這個程式的運行結果:

1 2 3 4 5 6 7 8 9 10 11 12 13 $ python string_processor.py Original: hOWz It GoInG? After uppercase: HOWZ IT GOING? After lowercase: howz it going? After uppercase then capitalize: Howz it going? After delspace: hOWzItGoInG? Original: The QUIck brOWn fOx After uppercase: THE QUICK BROWN FOX After lowercase: the quick brown fox After uppercase then capitalize: The quick brown fox After delspace: TheQUIckbrOWnfOx

綜上,我們可以發現,方法鏈有其用處,不過過度使用可能不太好。

jQuery中方法鏈的套用

目測對於方法鏈用得最多的,應該就是jQuery了。

代碼如下:

// chaining

$("#person").slideDown('slow')

.addClass('grouped')

.css('margin-left', '11px');

我們可以用這樣的用法來調用這個。

jQuery嚴重依賴於連結。這使得它很容易調用的幾個方法相同的選擇。這也使得代碼更清晰和防止執行相同的選擇幾次(提高性能)。沒有方法鏈的時候則是下面的樣子

代碼如下:

var p = $('#person');

p.slideDown('slow');

p.addClass('grouped');

p.css('margin-left', '11px');

看上去和設計模式中的builder很像,不同的是,這裡的p是方法,而不是一個類。

Javascript中方法鏈的套用

Javascript方法鏈示例

在之前我們說到Javascript高階函式的時候,說到的print('Hello')('World'),而這種用法的結果可能會變成這樣子。

代碼如下:

function f(i){

return function(e){

i+=e;

return function(e){

i+=e;

return function(e){

alert(i+e);

};

};

};

};
f(1)(2)(3)(4); //10

代碼如下:

var func = (function() {
return{
add: function () {
console.log('1');
return{
result: function () {
console.log('2');
}
}
}
}
})();

func.add().result();

實際上應該在每個function都要有個return this,於是就有了:

Func = (function() {
this.add = function(){
console.log('1');
return this;
};
this.result = function(){
console.log('2');
return this;
};
return this;
});

var func = new Func();
func.add().result();

可以將最後的兩句

var func = new Func();

func.add().result();

變成

new Func().add().result();

其他

最後作為一個迷惑的地方的小比較:

Method Chaining VS prototype Chaining

原型鏈與方法鏈在某些方面上是差不多的,不同的地方或許在於

原型鏈是需要用原型

方法鏈則是用方法

1.

原型鏈是需要用原型

2.

方法鏈則是用方法

相關詞條

熱門詞條

聯絡我們