渭南市工程建設(shè)項目審批平臺免費的關(guān)鍵詞優(yōu)化軟件
以下內(nèi)容均來自抖音號【it楠老師教java】的設(shè)計模式課程。
1、原理概述
子類對象(objectofsubtype/derivedclass)能夠替換程序(program)中父類對象(objectofbase/parentclass)出現(xiàn)的任何地方,并且保證原來程序的邏輯行為(behavior)不變及正確性不被破壞。
2、簡單的示例1
// 基類:鳥類public class Bird {public void fly () {System . out . println ( "I can fly" );} }// 子類:企鵝類public class Penguin extends Bird {// 企鵝不能飛,所以覆蓋了基類的 fly 方法,但這違反了里氏替換原則public void fly () {throw new UnsupportedOperationException ( "Penguins can't fly" );}}
// 飛行行為接口public interface Flyable {void fly ();}// 基類:鳥類public class Bird {}// 子類:能飛的鳥類public class FlyingBird extends Bird implements Flyable {@Overridepublic void fly () {System . out . println ( "I can fly" );}}// 子類:企鵝類,不實現(xiàn) Flyable 接口public class Penguin extends Bird {}
這里就該明確那些方法是通用的,哪些方法是部分能用的。
比如通用的方法可以放到class bird里。
public void say(){ System.out.println("我屬于鳥科")}
public void say(){ System.out.println("我又一雙翅膀,盡管不能飛")}
不同的用的方法,可以放到接口里比如有的鳥很小 有的鳥很大
interface? BigBird{ double height()}
interface? SmallBird{ double height()}
上述可能不太準(zhǔn)確,但是核心思想就是抽取公共的方法到類里,抽取特殊的方法到接口里。
再舉個例 比如
class? door{
//核心方法 只要是門 不管你啥樣的 你肯定又面積吧,有價格吧
int price();
int area();
}
但是有的門市防火門 有的是防盜門, 有的是....
interface FangHuo{ void canFangHuo()};
interface FangDao{ void canFangDao()};
3、示例2
我們再來看一個基于數(shù)據(jù)庫操作的案例。假設(shè)我們正在開發(fā)一個支持多種數(shù)據(jù)庫的程序,包括MySQL、PostgreSQL和SQLite。我們可以使用里氏替換原則來設(shè)計合適的類結(jié)構(gòu),確保代碼的可維護(hù)性和擴展性。 首先,我們定義一個抽象的Database 基類,它包含一些通用的數(shù)據(jù)庫操作方法, 如 connect() 、disconnect() 和 executeQuery() 。這些方法的具體實現(xiàn)將在 子類中完成。
public abstract class Database {public abstract void connect ();public abstract void disconnect ();public abstract void executeQuery ( String query );}
然后,為每種數(shù)據(jù)庫類型創(chuàng)建一個子類,繼承自 Database 基類。這些子類需要實現(xiàn)基類中定義的抽象方法,并可以添加特定于各自數(shù)據(jù)庫的方法。
這里新手要思考下 為什么用abstract class 怎么不用class 怎么不用interface
不用class,因為我這里還沒有具體到那類數(shù)據(jù)源,其實可以定義個jdbcDatabase ,定義屬性driver,url,user ,password。就是更一部的抽取
不用interface 因為connect close 和query是所有數(shù)據(jù)源都有操作!!!
public class MySQLDatabase extends Database {@Overridepublic void connect () {// 實現(xiàn) MySQL 的連接邏輯}@Overridepublic void disconnect () {// 實現(xiàn) MySQL 的斷開連接邏輯}@Overridepublic void executeQuery ( String query ) {// 實現(xiàn) MySQL 的查詢邏輯}// 其他針對 MySQL 的特定方法}public class PostgreSQLDatabase extends Database {// 類似地,為 PostgreSQL 實現(xiàn)相應(yīng)的方法}public class SQLiteDatabase extends Database {// 類似地,為 SQLite 實現(xiàn)相應(yīng)的方法}?
這樣設(shè)計的好處是,我們可以在不同的數(shù)據(jù)庫類型之間靈活切換,而不需要修改大量代碼。只要這些子類遵循里氏替換原則,我們就可以放心地使用基類的引用來操作不同類型的數(shù)據(jù)庫。例如:?
public class DatabaseClient {private Database database ;public DatabaseClient ( Database database ) {this . database = database ;}public void performDatabaseOperations () {database . connect ();database . executeQuery ( "SELECT * FROM users" );database . disconnect ();}}public class Main {public static void main ( String [] args ) {// 使用 MySQL 數(shù)據(jù)庫DatabaseClient client1 = new DatabaseClient ( new MySQLDatabase ());client1 . performDatabaseOperations ();// 切換到 PostgreSQL 數(shù)據(jù)庫DatabaseClient client2 = new DatabaseClient ( new PostgreSQLDatabase ());client2 . performDatabaseOperations ();// 切換到 SQLite 數(shù)據(jù)庫DatabaseClient client3 = new DatabaseClient ( new SQLiteDatabase ());client3 . performDatabaseOperations ();}}
好了,我們稍微總結(jié)一下。雖然從定義描述和代碼實現(xiàn)上來看,多態(tài)和里式替換有點類似,但它們關(guān)注的角度是不一樣的。多態(tài)是面向?qū)ο缶幊痰囊淮筇匦?#xff0c;也是面向?qū)ο缶幊陶Z言的一種語法。它是一種代碼實現(xiàn)的思路。而里式替換是一種設(shè)計原則,是用來指導(dǎo)繼承關(guān)系中子類該如何設(shè)計的,子類的設(shè)計要保證在替換父類的時候,不改變原有程序的邏輯以及不破壞原有程序的正確性。?
1.子類覆蓋或修改了基類的方法
當(dāng)子類覆蓋或修改基類的方法時,可能導(dǎo)致子類無法替換基類的實例而不引起問題。這違反了LSP,會導(dǎo)致代碼變得脆弱和不易維護(hù)。
public class Bird {public void fly () {System . out . println ( "I can fly" );}}public class Penguin extends Bird {@Overridepublic void fly () {throw new UnsupportedOperationException ( "Penguins can't fly" );}}
?
2、子類違反了基類的約束條件
當(dāng)子類違反了基類中定義的約束條件(如輸入、輸出或異常等),也會違反LSP。
public class Stack {private int top ;private int [] elements ;public Stack ( int size ) {elements = new int [ size ];top = - 1 ;}public void push ( int value ) {if ( top >= elements . length - 1 ) {throw new IllegalStateException ( "Stack is full" );} elements [ ++ top ] = value ;}public int pop () {if ( top < 0 ) {throw new IllegalStateException ( "Stack is empty" );}return elements [ top -- ];}}// 正數(shù)的棧public class NonNegativeStack extends Stack {public NonNegativeStack ( int size ) {super ( size );}@Overridepublic void push ( int value ) {if ( value < 0 ) {throw new IllegalArgumentException ( "Only non-negative values are allowed" );}super . push ( value );}}// 正確的寫法public class NonNegativeStack extends Stack {public NonNegativeStack ( int size ) {super ( size );}public void pushNonNegative ( int value ) {if ( value < 0 ) {throw new IllegalArgumentException ( "Only non-negative values are allowed" );}super . push ( value );}}
這里感覺給的資料有問題。。。等我看完視頻在說?