設計模式—里氏替換原則

1.概念

里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。

通俗的講:

1.所有引用基類的地方必須能透明的使用其子類的對象。其父類可以替換成子類,而子類不能替換成父類;

2.子類可以擴展父類的功能,但不能改變父類原有的功能;

2.舉例

例如:鳥一般都會飛行,如燕子的飛行速度大概是每小時 120 千米。但是新西蘭的幾維鳥由于翅膀退化無法飛行。假如要設計一個實例,計算這兩種鳥飛行 300 千米要花費的時間。顯然,拿燕子來測試這段代碼,結果正確,能計算出所需要的時間;但拿幾維鳥來測試,結果會發生“除零異常”或是“無窮大”,明顯不符合預期,類圖如下:

未遵守里氏替換原則:

 
package com.example.demo.principle;public class LSPtest {public static void main(String[] args) {Bird bird1 = new Swallow();Bird bird2 = new BrownKiwi();bird1.setSpeed(120);bird2.setSpeed(120);System.out.println("如果飛行300公里:");try {System.out.println("燕子將飛行" + bird1.getFlyTime(300) + "小時.");System.out.println("幾維鳥將飛行" + bird2.getFlyTime(300) + "小時。");} catch (Exception err) {System.out.println("發生錯誤了!");}}
}//鳥類
class Bird {double flySpeed;public void setSpeed(double speed) {flySpeed = speed;}public double getFlyTime(double distance) {return (distance / flySpeed);}
}//燕子類
class Swallow extends Bird {
}//幾維鳥類
class BrownKiwi extends Bird {public void setSpeed(double speed) {flySpeed = 0;}}------------------   運行結果   --------------------------如果飛行300公里:
燕子將飛行2.5小時.
幾維鳥將飛行Infinity小時。Process finished with exit code 0

這個設計存在的問題:

  • 幾維鳥類重寫了鳥類的 setSpeed(double speed) 方法,這違背了里氏替換原則。

  • 燕子和幾維鳥都是鳥類,但是父類抽取的共性有問題,幾維鳥的的飛行不是正常鳥類的功能,需要特殊處理,應該抽取更加共性的功能。

遵守里氏替換原則

優化:

取消幾維鳥原來的繼承關系,定義鳥和幾維鳥的更一般的父類,如動物類,它們都有奔跑的能力。幾維鳥的飛行速度雖然為 0,但奔跑速度不為 0,可以計算出其奔跑 300 千米所要花費的時間。

package com.example.demo.principle;public class Lsptest2 {public static void main(String[] args) {Animal animal1 = new Bird();Animal animal2 = new BrownKiwi();animal1.setRunSpeed(120);animal2.setRunSpeed(180);System.out.println("如果奔跑300公里:");try {System.out.println("鳥類將奔跑" + animal1.getRunSpeed(300) + "小時.");System.out.println("幾維鳥將奔跑" + animal2.getRunSpeed(300) + "小時。");Bird bird = new Swallow();bird.setFlySpeed(150);System.out.println("如果飛行300公里:");System.out.println("燕子將飛行" + bird.getFlyTime(300) + "小時.");} catch (Exception err) {System.out.println("發生錯誤了!");}}
}/*** 動物類,抽象的功能更加具有共性*/class  Animal{Double runSpeed;public void setRunSpeed(double runSpeed) {this.runSpeed = runSpeed;}public double getRunSpeed(double distince) {return distince/runSpeed;}}/*** 鳥類繼承動物類*/class Bird extends Animal{double flySpeed;public void setFlySpeed(double flySpeed) {this.flySpeed = flySpeed;}public double getFlyTime(double distince) {return distince/flySpeed;}}/*** 幾維鳥繼承動物類*/class  BrownKiwi extends  Animal{}/*** 燕子繼承鳥類  飛行屬于燕子的特性,*/class Swallow extends  Bird{}---------   運行結果  -----------------
如果奔跑300公里:
鳥類將奔跑2.5小時.
幾維鳥將奔跑1.6666666666666667小時。
如果飛行300公里:
燕子將飛行2.0小時.

3.優點

  • 代碼共享,減少創建類的工作量,每個子類都擁有父類的方法和屬性;

  • 提高代碼的重用性;

  • 提高代碼的可擴展性;

  • 提高產品或項目的開放性;

4.缺點

  • 繼承是侵入性的。只要繼承,就必須擁有父類的所有屬性和方法;

  • 降低代碼的靈活性。子類必須擁有父類的屬性和方法,讓子類自由的世界中多了些約束;

  • 增強了耦合性。當父類的常量、變量和方法被修改時,需要考慮子類的修改,而且在缺乏規范的環境下,這種修改可能帶來非常糟糕的結果————大段的代碼需要重構。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/168126.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/168126.shtml
英文地址,請注明出處:http://en.pswp.cn/news/168126.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring注解方式整合第三方框架

目錄 Spring整合MyBatis 原有xml方式整合配置如下 注解方式: Import可以導入如下三種類 第三方框架是指由其他開發者或團隊開發的軟件模塊或庫,供開發者在自己的應用程序中使用。這些框架通常提供了一系列已經封裝好的功能或工具,可節省開…

使用flask返回json格式的數據

Flask Flask是一個使用Python編寫的輕量級Web框架,它的設計理念是保持簡單、靈活和易擴展。它的核心是Werkzeug和Jinja2,并且它本身只提供了非常基礎的Web框架功能,例如路由和請求處理等。 使用Flask可以快速創建一個Web應用程序,…

跳躍游戲Ⅱ[中等]

優質博文&#xff1a;IT-BLOG-CN 一、題目 給定一個長度為n的0索引整數數組nums。初始位置為nums[0]。每個元素nums[i]表示從索引i向前跳轉的最大長度。換句話說&#xff0c;如果你在nums[i]處&#xff0c;你可以跳轉到任意nums[i j]處: 0 < j < nums[i] i j < n …

【Python 訓練營】N_8 打印阿姆斯特朗數

題目 輸入一個數&#xff0c;判斷是否為阿姆斯特朗數&#xff0c;阿姆斯特朗數指一個n位正整數等于其各位數字的n次方之和。其中n為3時是水仙花數。 分析 利用循環&#xff0c;獲取數的長度&#xff0c;根據長度和定義&#xff0c;拆分出來運算 答案 while True:n int(in…

【Python 訓練營】N_7 打印水仙花數

題目 打印出1000以內所有的"水仙花數"&#xff0c;所謂"水仙花數"是指一個三位數&#xff0c;其各位數字立方和等于該數本身。例如&#xff1a;153是一個"水仙花數"&#xff0c;因為1531的三次方&#xff0b;5的三次方&#xff0b;3的三次方。 …

數學啟發式

學習資料&#xff1a; 優化求解器 | Gurobi 數學啟發式算法&#xff1a;參數類型與案例實現 數學啟發式算法 | 可行性泵 (Feasibility Pump)算法精講&#xff1a;一份讓您滿意的【理論介紹編程實現數值實驗】學習筆記(PythonGurobi實現) 大佬到底是大佬&#xff01;這些資料太…

Mac Ubuntu雙系統解決WiFi和WiFi 5G網絡不可用問題

文章目錄 設備信息1. Ubuntu WiFi不可用解決方式查看Mac的網卡型號根據網卡型號搜索獲取到的解決方法查看WiFi名字問題參考鏈接 2. 解決WiFi重啟后失效問題打開終端創建.sh腳本文件編輯腳本文件復制粘貼腳本修改腳本權限創建并編輯systemd service文件復制粘貼下文到systemd se…

Typescript怎樣對URL參數進行編碼?

URL中的參數需要進行編碼&#xff08;URL encoding&#xff09;是為了確保傳輸的參數不包含特殊字符&#xff0c;同時確保數據的可靠性和安全性。 特殊字符如空格、&、?等在URL中有特殊含義&#xff0c;如果直接包含在參數值中&#xff0c;可能會導致解析錯誤或者安全問題…

只考數據結構,計算機評級C+,成都信息工程大學考情分析

成都信息工程大學(C) 考研難度&#xff08;☆☆&#xff09; 內容&#xff1a;23考情概況&#xff08;擬錄取和復試分析&#xff09;、院校概況、24專業目錄、23復試詳情、各專業考情分析、各科目考情分析。 正文1715字&#xff0c;預計閱讀&#xff1a;3分鐘 2023考情概況 …

Java實現求最大值

1 問題 接收用戶輸入的3個整數&#xff0c;如何將最大值作為結果輸出。 2 方法 采用“截圖文字代碼”的方式描述。 引入輸入包調用main()函數&#xff0c;提示并接收用戶輸入的3個整數&#xff0c;并交由變量a b c來保存。對接收的3個數據進行比較&#xff0c;先比較a和b&#…

原型 原型對象 原型鏈

在面向開發對象開發過程中對每一個實例添加方法&#xff0c;會使每一個對象都存在該添加方法造成空間浪費 通過對原型添加公共的屬性或方法&#xff0c;使所有實例對象都可訪問 原型為了共享公共的成員 prototype 原型: JS為每個構造函數提供一個屬性prototype(原型),它的值…

PostgreSQL數據庫初接觸

PostgreSQL默認端口為5432 windows下服務名為PostgreSQL-x64-10 10為版本 進程名為pg-ctl.exe 備份數據庫命令&#xff1a; pg_dump -h localhost -p 5432 -U postgres -f d:\20231124.dmp tcsl7//tcsl7為數據庫名 開始用-d 指定數據庫&#xff0c;后來提示沒-d參數 還…

在服務器復用他人的anaconda3(免安裝)

在服務器復用他人的anaconda3 1. 復制他人的anaconda3文件夾2. 修改配置文件3. 修改環境路徑和包路徑 1. 復制他人的anaconda3文件夾 cp -r /home/xxx/anaconda3 /home/your_username2. 修改配置文件 vim anaconda3/etc/profile.d/conda.sh # 替換原來的用戶名為自己的用戶名…

SELinux零知識學習二十八、SELinux策略語言之類型強制(13)

接前一篇文章:SELinux零知識學習二十七、SELinux策略語言之類型強制(12) 二、SELinux策略語言之類型強制 4. 類型規則 類型規則在創建客體或在運行過程中重新標記時指定其默認類型。在策略語言中定義了兩個類型規則: type_transtition在域轉換過程中標記行為發生時以及創…

jQuery 3.0 新增了哪些特性?(jQuery 3 所引入的那些最重要的變化)

文章目錄 前言簡介新增特性Use of requestAnimationFrame() for Animationsunwrap() 方法 有變更的特性data() 方法Deferred 對象SVG 文檔 已廢棄、已移除的方法和屬性廢棄 bind()、unbind()、delegate() 和 undelegate() 方法移除 load()、unload() 和 error() 方法移除 conte…

計算機應用基礎_錯題集_OutLook操作題_操作系統應用題_電子表格---網絡教育統考工作筆記005

6、(說明:考生單擊窗口下方的“打開[Outlook]應用程序”啟動Outlook) 按以下要求保存草稿。 收件人:test_xiao_ming@163.com

深眸科技聚焦AI機器視覺檢測,驅動3C電子行業集成創新實現新需求

隨著消費的升級及國家政策的助推&#xff0c;國內3C電子市場不斷擴大&#xff0c;行業實現高速發展。近年來&#xff0c;3C電子產品持續迭代&#xff0c;生產工藝也逐漸復雜化&#xff0c;相關生產線定位組裝、零部件檢測、整機產品檢測等環節&#xff0c;亟需使用具備較強適應…

C語言-字符串逆序

輸入一個字符串&#xff0c;對該字符串進行逆序&#xff0c;輸出逆序后的字符串。 輸入格式&#xff1a; 輸入在一行中給出一個不超過80個字符長度的、以回車結束的非空字符串。 輸出格式&#xff1a; 在一行中輸出逆序后的字符串。 輸入樣例&#xff1a; Hello World…

云原生系列Go語言篇-編寫測試Part 2

基準測試 確定代碼是快或慢非常復雜。我們不用自己計算&#xff0c;應使用Go測試框架內置的基準測試。下面來看??第15章的GitHub代碼庫??sample_code/bench目錄下的函數&#xff1a; func FileLen(f string, bufsize int) (int, error) {file, err : os.Open(f)if err ! …

【XSLVGL2.0】如何設置壁紙

XSLVGL2.0 開發手冊 XSLVGL2.0 Brief 1、概述2、設置方法 1、概述 設置壁紙使用的是LVGL默認的方式。一般而言&#xff0c;若非必要&#xff0c;建議不要去設置此功能&#xff0c;此功能對性能影響頗大。 2、設置方法 在main.c的 static int InitLvgl(void *cookie) 函數中…