官术网_书友最值得收藏!

1.3 封裝

封裝的目的是將信息隱藏。一般而言,我們討論的封裝是封裝數據和封裝實現。這一節將討論更廣義的封裝,不僅包括封裝數據和封裝實現,還包括封裝類型和封裝變化。

1.3.1 封裝數據

在許多語言的對象系統中,封裝數據是由語法解析來實現的,這些語言也許提供了private、public、protected等關鍵字來提供不同的訪問權限。

但JavaScript并沒有提供對這些關鍵字的支持,我們只能依賴變量的作用域來實現封裝特性,而且只能模擬出public和private這兩種封裝性。

除了ECMAScript 6中提供的let之外,一般我們通過函數來創建作用域:

        var myObject = (function(){
            var __name = 'sven';    //私有(private)變量
            return {
              getName: function(){    //公開(public)方法
                  return __name;
              }
            }
        })();

        console.log( myObject.getName() );    //輸出:sven
        console.log( myObject.__name )     //輸出:undefined

另外值得一提的是,在ECMAScript 6中,還可以通過Symbol創建私有屬性。詳情可參閱https://github.com/lukehoban/es6features,二維碼見右邊。

1.3.2 封裝實現

上一節描述的封裝,指的是數據層面的封裝。有時候我們喜歡把封裝等同于封裝數據,但這是一種比較狹義的定義。

封裝的目的是將信息隱藏,封裝應該被視為“任何形式的封裝”,也就是說,封裝不僅僅是隱藏數據,還包括隱藏實現細節、設計細節以及隱藏對象的類型等。

從封裝實現細節來講,封裝使得對象內部的變化對其他對象而言是透明的,也就是不可見的。對象對它自己的行為負責。其他對象或者用戶都不關心它的內部實現。封裝使得對象之間的耦合變松散,對象之間只通過暴露的API接口來通信。當我們修改一個對象時,可以隨意地修改它的內部實現,只要對外的接口沒有變化,就不會影響到程序的其他功能。

封裝實現細節的例子非常之多。拿迭代器來說明,迭代器的作用是在不暴露一個聚合對象的內部表示的前提下,提供一種方式來順序訪問這個聚合對象。我們編寫了一個each函數,它的作用就是遍歷一個聚合對象,使用這個each函數的人不用關心它的內部是怎樣實現的,只要它提供的功能正確便可以。即使each函數修改了內部源代碼,只要對外的接口或者調用方式沒有變化,用戶就不用關心它內部實現的改變。

1.3.3 封裝類型

封裝類型是靜態類型語言中一種重要的封裝方式。一般而言,封裝類型是通過抽象類和接口來進行的詳情可參閱1.2節中的Animal示例。。把對象的真正類型隱藏在抽象類或者接口之后,相比對象的類型,客戶更關心對象的行為。在許多靜態語言的設計模式中,想方設法地去隱藏對象的類型,也是促使這些模式誕生的原因之一。比如工廠方法模式、組合模式等。

當然在JavaScript中,并沒有對抽象類和接口的支持。JavaScript本身也是一門類型模糊的語言。在封裝類型方面,JavaScript沒有能力,也沒有必要做得更多。對于JavaScript的設計模式實現來說,不區分類型是一種失色,也可以說是一種解脫。在后面章節的學習中,我們可以慢慢了解這一點。

1.3.4 封裝變化

從設計模式的角度出發,封裝在更重要的層面體現為封裝變化

《設計模式》一書曾提到如下文字:

“考慮你的設計中哪些地方可能變化,這種方式與關注會導致重新設計的原因相反。它不是考慮什么時候會迫使你的設計改變,而是考慮你怎樣才能夠在不重新設計的情況下進行改變。這里的關鍵在于封裝發生變化的概念,這是許多設計模式的主題。”

這段文字即是《設計模式》提到的“找到變化并封裝之”。《設計模式》一書中共歸納總結了23種設計模式。從意圖上區分,這23種設計模式分別被劃分為創建型模式、結構型模式和行為型模式。

拿創建型模式來說,要創建一個對象,是一種抽象行為,而具體創建什么對象則是可以變化的,創建型模式的目的就是封裝創建對象的變化。而結構型模式封裝的是對象之間的組合關系。行為型模式封裝的是對象的行為變化。

通過封裝變化的方式,把系統中穩定不變的部分和容易變化的部分隔離開來,在系統的演變過程中,我們只需要替換那些容易變化的部分,如果這些部分是已經封裝好的,替換起來也相對容易。這可以最大程度地保證程序的穩定性和可擴展性。

從《設計模式》副標題“可復用面向對象軟件的基礎”可以知道,這本書理應教我們如何編寫可復用的面向對象程序。這本書把大多數筆墨都放在如何封裝變化上面,這跟編寫可復用的面向對象程序是不矛盾的。當我們想辦法把程序中變化的部分封裝好之后,剩下的即是穩定而可復用的部分了。

主站蜘蛛池模板: 通渭县| 邳州市| 开封县| 海林市| 浦东新区| 清流县| 广德县| 嘉定区| 江北区| 永修县| 平潭县| 中江县| 金阳县| 合川市| 元谋县| 平谷区| 双流县| 拉孜县| 同江市| 余姚市| 汝州市| 尉氏县| 舟山市| 崇仁县| 柳州市| 肥东县| 改则县| 商丘市| 惠东县| 阿坝| 内丘县| 昆山市| 南岸区| 四平市| 黔江区| 左云县| 海宁市| 广州市| 曲麻莱县| 徐闻县| 二手房|