做老師好還是網(wǎng)站編輯好常見的系統(tǒng)優(yōu)化軟件
抽象類概述
在Java中abstract是抽象的意思,如果一個類中的某個方法的具體實現(xiàn)不能確定,就可以申明成abstract修飾的抽象方法(不能寫方法體了),這個類必須用abstract修飾,被稱為抽象類。
抽象方法定義:修飾符 abstract 返回值類型 方法名稱(形參列表);,只有方法簽名,沒有方法體,使用了abstract修飾。
抽象類定義:修飾符 abstract class 類名{ ?}
抽象類可以理解成類的不完整設(shè)計圖,是用來被子類繼承的。
抽象類的作用: 可以被子類繼承、充當(dāng)模板的、同時也可以提高代碼復(fù)用。
怎么理解模板?相當(dāng)于以一篇缺少中間內(nèi)容的作文作為模板,結(jié)構(gòu)都不用變,我只要充實下中間的內(nèi)容,那么子類以抽象類作為模板,只要實現(xiàn)下抽象方法即可。
示例:
public abstract class Animal {private String name;public abstract void run();public String getName() {return name;}public void setName(String name) {this.name = name;}
}
抽象類的案例
系統(tǒng)需求
某加油站推出了2種支付卡,一種是預(yù)存10000的金卡,后續(xù)加油享受8折優(yōu)惠,另一種是預(yù)存5000的銀卡 ,后續(xù)加油享受8.5折優(yōu)惠。
請分別實現(xiàn)2種卡片進入收銀系統(tǒng)后的邏輯,卡片需要包含主人名稱,余額,支付功能。
分析實現(xiàn)
創(chuàng)建一張卡片父類:定義屬性包括主人名稱、余額、支付功能(具體實現(xiàn)交給子類)
創(chuàng)建一張白金卡類:重寫支付功能,按照原價的8折計算輸出。 創(chuàng)建一張銀卡類:重寫支付功能,按照原價的8.5折計算輸出。
代碼
/**抽象父類*/
public abstract class Card {private String name; // 主人名稱private double money;/**子類一定要支付的,但是每個子類支付的情況不一樣,所以父類把支付定義成抽象方法,交給具體子類實現(xiàn)*/public abstract void pay(double money);public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}
}
/**金卡*/
public class GoldCard extends Card{@Overridepublic void pay(double money) {// 優(yōu)惠后的金額算出來:double rs = money * 0.8;double lastMoney = getMoney() - rs;System.out.println(getName() + "當(dāng)前賬戶總金額:"+ getMoney() +",當(dāng)前消費了:" + rs +",消費后余額剩余:" +lastMoney);setMoney(lastMoney); // 更新賬戶對象余額}
}
?銀卡差不多
抽象類的特征、注意事項
1、有得有失: 得到了抽象方法,失去了創(chuàng)建對象的能力。
2、抽象類為什么不能創(chuàng)建對象?? 反證法。
3、類有的成員(成員變量、方法、構(gòu)造器)抽象類都具備
4、抽象類中不一定有抽象方法,有抽象方法的類一定是抽象類
5、一個類繼承了抽象類必須重寫完抽象類的全部抽象方法,否則這個類也必須定義成抽象類。
6、不能用abstract修飾變量、代碼塊、構(gòu)造器。
final和abstract是什么關(guān)系?
互斥關(guān)系
abstract定義的抽象類作為模板讓子類繼承,final定義的類不能被繼承。
抽象方法定義通用功能讓子類重寫,final定義的方法子類不能重寫。
抽象類的應(yīng)用知識:模板方法模式
概述
模板方法模式(Template Method Pattern)是一種行為設(shè)計模式,它在一個方法中定義一個算法的骨架,允許子類在不改變算法結(jié)構(gòu)的情況下重新定義某些步驟的具體內(nèi)容。換句話說,模板方法模式封裝了不變的部分,而將可變的部分留給子類來實現(xiàn)。
在模板方法模式中,通常有一個抽象類(或稱為模板類),它定義了算法的骨架和步驟的順序。這個抽象類還包含一些抽象方法或鉤子方法(hook methods),這些方法是抽象的,需要在子類中具體實現(xiàn)。子類通過實現(xiàn)這些抽象方法,可以重新定義算法中的某些步驟,以滿足特定的需求。
使用模板方法模式的好處有以下幾點:
- 代碼復(fù)用:模板方法模式將算法的不變部分封裝在父類中,而可變部分則留給子類來實現(xiàn)。這樣,子類可以在不改變算法結(jié)構(gòu)的情況下,通過覆蓋父類的方法來實現(xiàn)自己的邏輯,從而實現(xiàn)了代碼的復(fù)用。
- 擴展性:由于算法的可變部分被抽象出來,子類可以通過擴展父類來實現(xiàn)新的功能。這符合開閉原則,即對擴展開放,對修改封閉。
- 控制子類行為:模板方法模式通過定義算法的骨架和步驟順序,可以控制子類的行為。父類中的模板方法規(guī)定了算法的整體流程,而子類則通過實現(xiàn)抽象方法來參與這個流程。
然而,模板方法模式也有一些潛在的缺點:
- 類個數(shù)增加:對于每個不同的實現(xiàn),都需要定義一個子類,這可能會導(dǎo)致類的個數(shù)增加,系統(tǒng)更加龐大和復(fù)雜。
- 反向控制結(jié)構(gòu):父類中的抽象方法由子類實現(xiàn),子類執(zhí)行的結(jié)果會影響父類的結(jié)果,這導(dǎo)致一種反向的控制結(jié)構(gòu)。這可能會增加代碼閱讀的難度和維護的復(fù)雜性。
在實際應(yīng)用中,模板方法模式通常用于實現(xiàn)一些具有固定流程的操作,如文件操作、數(shù)據(jù)庫操作、網(wǎng)絡(luò)通信等。在這些場景中,通過使用模板方法模式,可以將不變的部分封裝起來,而將可變的部分留給子類來實現(xiàn),從而提高代碼的復(fù)用性和可維護性。
什么時候使用模板方法模式
使用場景說明:當(dāng)系統(tǒng)中出現(xiàn)同一個功能多處在開發(fā),而該功能中大部分代碼是一樣的,只有其中部分可能不同的時候。
模板方法模式實現(xiàn)步驟
把功能定義成一個所謂的模板方法,放在抽象類中,模板方法中只定義通用且能確定的代碼。
模板方法中不能確定的功能定義成抽象方法讓具體子類去實現(xiàn)。
案例:銀行利息結(jié)算系統(tǒng)
需求:
某軟件公司要為某銀行的業(yè)務(wù)支撐系統(tǒng)開發(fā)一個利息結(jié)算系統(tǒng),賬戶有活期和定期賬戶兩種。
活期是0.35%,定期是 1.75%,定期如果滿10萬額外給予3%的收益。
結(jié)算利息要先進行用戶名、密碼驗證,驗證失敗直接提示,登錄成功進行結(jié)算。
分析:
實現(xiàn)步驟:
創(chuàng)建一個抽象的賬戶類Account作為父類模板,提供屬性(卡號,余額)。
在父類Account中提供一個模板方法實現(xiàn)登錄驗證,利息結(jié)算、利息輸出。
具體的利息結(jié)算定義成抽象方法,交給子類實現(xiàn)。
定義活期賬戶類,讓子類重寫實現(xiàn)具體的結(jié)算方法。
定義定期賬戶類,讓子類重寫實現(xiàn)具體的結(jié)算方法。
創(chuàng)建賬戶對象,完成相關(guān)功能。
代碼:
public abstract class Account {private String cardId;private double money;public Account() {}public Account(String cardId, double money) {this.cardId = cardId;this.money = money;}/**模板方法*/public final void handle(String loginName , String passWord ){// a.判斷登錄是否成功if("itheima".equals(loginName) && "123456".equals(passWord)){System.out.println("登錄成功。。");// b.正式結(jié)算利息// 當(dāng)前模板方法知道所有子類賬戶都要結(jié)算利息,但是具體怎么結(jié)算,模板不清楚,交給具體的子類來計算double result = calc();// c.輸出利息詳情System.out.println("本賬戶利息是:"+ result);}else{System.out.println("用戶名或者密碼錯誤了");}}public abstract double calc();public String getCardId() {return cardId;}public void setCardId(String cardId) {this.cardId = cardId;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}
}
/**活期賬戶*/
public class CurrentAccount extends Account {public CurrentAccount(String cardId, double money) {super(cardId, money);}@Overridepublic double calc() {// b.正式結(jié)算利息double result = getMoney() * 0.0175; // 結(jié)算利息了return result;}}
public class Test {public static void main(String[] args) {CurrentAccount acc = new CurrentAccount("ICBC-111", 100000);acc.handle("itheima", "123456");}
}
模板方法我們是建議使用final修飾的,這樣會更專業(yè),那么為什么呢?
答:模板方法是給子類直接使用的,不是讓子類重寫的, 一旦子類重寫了模板方法就失效了。
模板方法模式解決了什么問題? ?
極大的提高了代碼的復(fù)用性。
模板方法已經(jīng)定義了通用結(jié)構(gòu),模板不能確定的定義成抽象方法。 ?
使用者只需要關(guān)心自己需要實現(xiàn)的功能即可。