<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧

        來源:懂視網 責編:小采 時間:2020-11-27 21:01:57
        文檔

        深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧

        深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧:前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。 英文原文:http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript
        推薦度:
        導讀深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧:前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。 英文原文:http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript

        前言
        本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。

        英文原文:http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/

        開閉原則的描述是:

        Subtypes must be substitutable for their base types.
        派生類型必須可以替換它的基類型。

        在面向對象編程里,繼承提供了一個機制讓子類和共享基類的代碼,這是通過在基類型里封裝通用的數據和行為來實現的,然后已經及類型來聲明更詳細的子類型,為了應用里氏替換原則,繼承子類型需要在語義上等價于基類型里的期望行為。

        為了來更好的理解,請參考如下代碼:
        代碼如下:
        function Vehicle(my) {
        var my = my || {};
        my.speed = 0;
        my.running = false;

        this.speed = function() {
        return my.speed;
        };
        this.start = function() {
        my.running = true;
        };
        this.stop = function() {
        my.running = false;
        };
        this.accelerate = function() {
        my.speed++;
        };
        this.decelerate = function() {
        my.speed--;
        }, this.state = function() {
        if (!my.running) {
        return "parked";
        }
        else if (my.running && my.speed) {
        return "moving";
        }
        else if (my.running) {
        return "idle";
        }
        };
        }

        上述代碼我們定義了一個Vehicle函數,其構造函數為vehicle對象提供了一些基本的操作,我們來想想如果當前函數當前正運行在服務客戶的產品環境上,如果現在需要添加一個新的構造函數來實現加快移動的vehicle。思考以后,我們寫出了如下代碼:
        代碼如下:
        function FastVehicle(my) {
        var my = my || {};

        var that = new Vehicle(my);
        that.accelerate = function() {
        my.speed += 3;
        };
        return that;
        }

        在瀏覽器的控制臺我們都測試了,所有的功能都是我們的預期,沒有問題,FastVehicle的速度增快了3倍,而且繼承他的方法也是按照我們的預期工作。此后,我們開始部署這個新版本的類庫到產品環境上,可是我們卻接到了新的構造函數導致現有的代碼不能支持執行了,下面的代碼段揭示了這個問題:
        代碼如下:
        var maneuver = function(vehicle) {
        write(vehicle.state());
        vehicle.start();
        write(vehicle.state());
        vehicle.accelerate();
        write(vehicle.state());
        write(vehicle.speed());
        vehicle.decelerate();
        write(vehicle.speed());
        if (vehicle.state() != "idle") {
        throw "The vehicle is still moving!";
        }
        vehicle.stop();
        write(vehicle.state());
        };

        根據上面的代碼,我們看到拋出的異常是“The vehicle is still moving!”,這是因為寫這段代碼的作者一直認為加速(accelerate)和減速(decelerate)的數字是一樣的。但FastVehicle的代碼和Vehicle的代碼并不是完全能夠替換掉的。因此,FastVehicle違反了里氏替換原則。

        在這點上,你可能會想:“但,客戶端不能老假定vehicle都是按照這樣的規則來做”,里氏替換原則(LSP)的妨礙(譯者注:就是妨礙實現LSP的代碼)不是基于我們所想的繼承子類應該在行為里確保更新代碼,而是這樣的更新是否能在當前的期望中得到實現。

        上述代碼這個case,解決這個不兼容的問題需要在vehicle類庫或者客戶端調用代碼上進行一點重新設計,或者兩者都要改。

        減少LSP妨礙
        那么,我們如何避免LSP妨礙?不幸的話,并不是一直都是可以做到的。我們這里有幾個策略我們處理這個事情。

        契約(Contracts)
        處理LSP過分妨礙的一個策略是使用契約,契約清單有2種形式:執行說明書(executable specifications)和錯誤處理,在執行說明書里,一個詳細類庫的契約也包括一組自動化測試,而錯誤處理是在代碼里直接處理的,例如在前置條件,后置條件,常量檢查等,可以從Bertrand Miller的大作《契約設計》中查看這個技術。雖然自動化測試和契約設計不在本篇文字的范圍內,但當我們用的時候我還是推薦如下內容:

        檢查使用測試驅動開發(Test-Driven Development)來指導你代碼的設計
        設計可重用類庫的時候可隨意使用契約設計技術
        對于你自己要維護和實現的代碼,使用契約設計趨向于添加很多不必要的代碼,如果你要控制輸入,添加測試是非常有必要的,如果你是類庫作者,使用契約設計,你要注意不正確的使用方法以及讓你的用戶使之作為一個測試工具。

        避免繼承
        避免LSP妨礙的另外一個測試是:如果可能的話,盡量不用繼承,在Gamma的大作《Design Patterns – Elements of Reusable Object-Orineted Software》中,我們可以看到如下建議:

        Favor object composition over class inheritance
        盡量使用對象組合而不是類繼承

        有些書里討論了組合比繼承好的唯一作用是靜態類型,基于類的語言(例如,在運行時可以改變行為),與JavaScript相關的一個問題是耦合,當使用繼承的時候,繼承子類型和他們的基類型耦合在一起了,就是說及類型的改變會影響到繼承子類型。組合傾向于對象更小化,更容易想靜態和動態語言語言維護。

        與行為有關,而不是繼承
        到現在,我們討論了和繼承上下文在內的里氏替換原則,指示出JavaScript的面向對象實。不過,里氏替換原則(LSP)的本質不是真的和繼承有關,而是行為兼容性。JavaScript是一個動態語言,一個對象的契約行為不是對象的類型決定的,而是對象期望的功能決定的。里氏替換原則的初始構想是作為繼承的一個原則指南,等價于對象設計中的隱式接口。

        舉例來說,讓我們來看一下Robert C. Martin的大作《敏捷軟件開發 原則、模式與實踐》中的一個矩形類型:

        矩形例子
        考慮我們有一個程序用到下面這樣的一個矩形對象:
        代碼如下:
        var rectangle = {
        length: 0,
        width: 0
        };
        [code]
        過后,程序有需要一個正方形,由于正方形就是一個長(length)和寬(width)都一樣的特殊矩形,所以我們覺得創建一個正方形代替矩形。我們添加了length和width屬性來匹配矩形的聲明,但我們覺得使用屬性的getters/setters一般我們可以讓length和width保存同步,確保聲明的是一個正方形:
        [code]
        var square = {};
        (function() {
        var length = 0, width = 0;
        // 注意defineProperty方式是262-5版的新特性
        Object.defineProperty(square, "length", {
        get: function() { return length; },
        set: function(value) { length = width = value; }
        });
        Object.defineProperty(square, "width", {
        get: function() { return width; },
        set: function(value) { length = width = value; }
        });
        })();

        不幸的是,當我們使用正方形代替矩形執行代碼的時候發現了問題,其中一個計算矩形面積的方法如下:
        代碼如下:
        var g = function(rectangle) {
        rectangle.length = 3;
        rectangle.width = 4;
        write(rectangle.length);
        write(rectangle.width);
        write(rectangle.length * rectangle.width);
        };

        該方法在調用的時候,結果是16,而不是期望的12,我們的正方形square對象違反了LSP原則,square的長度和寬度屬性暗示著并不是和矩形100%兼容,但我們并不總是這樣明確的暗示。解決這個問題,我們可以重新設計一個shape對象來實現程序,依據多邊形的概念,我們聲明rectangle和square,relevant。不管怎么說,我們的目的是要說里氏替換原則并不只是繼承,而是任何方法(其中的行為可以另外的行為)。

        總結
        里氏替換原則(LSP)表達的意思不是繼承的關系,而是任何方法(只要該方法的行為能體會另外的行為就行)。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧

        深入理解JavaScript系列(8)S.O.L.I.D五大原則之里氏替換原則LSP_javascript技巧:前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。 英文原文:http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 免费无遮挡无遮羞在线看| 亚洲一日韩欧美中文字幕在线| 国产精品视频全国免费观看| 永久黄网站色视频免费| 亚洲熟妇AV一区二区三区宅男| 色片在线免费观看| 亚洲高清无码综合性爱视频| 亚洲av鲁丝一区二区三区| 国产成人免费ā片在线观看老同学| 日本精品人妻无码免费大全| 亚洲区不卡顿区在线观看| 日本一区二区三区免费高清在线| 免费a级毛片18以上观看精品| 免费精品视频在线| 久久久久一级精品亚洲国产成人综合AV区 | 亚洲av无码无在线观看红杏| 亚洲特级aaaaaa毛片| 最刺激黄a大片免费网站| 亚洲国产日韩在线人成下载| 和日本免费不卡在线v| 亚洲欧美黑人猛交群| 免费在线观看黄色毛片| 99在线免费视频| 亚洲视频一区二区在线观看| 一区二区三区免费在线视频| 亚洲中文字幕无码久久2017| 亚洲欧洲专线一区| 亚洲国产精品国产自在在线| 91免费福利视频| 亚洲性色高清完整版在线观看| 国内精品免费视频自在线| 久久久久亚洲AV无码专区首JN| 五月婷婷综合免费| 四虎精品免费永久免费视频| 国产亚洲精品自在久久| 香蕉国产在线观看免费| 亚洲最大成人网色| 蜜臀91精品国产免费观看| 国产一级a毛一级a看免费人娇| 免费一级一片一毛片| 午夜免费啪视频在线观看 |