java 抽象属性 设计_Java 抽象类与模板设计模式详解
抽象類
抽象類是為了方法覆寫而提供的類結(jié)構(gòu),因為其無法自身直接進行對象實例化操作,所以在實際應(yīng)用中,抽象類主要目的是進行過程操作使用,當你要使用抽象類進行開發(fā)的時候,往往都是在你設(shè)計中需要解決類繼承問題時所帶來的的代碼重復(fù)處理。
普通類是一個完善的功能類,可以直接產(chǎn)生實例化對象,并且在普通類中可以包含有構(gòu)造方法、普通方法、static方法、常量和變量等內(nèi)容。而抽象類是指在普通類的結(jié)構(gòu)里面增加抽象方法的組成部分。
在這里小編建了一個前端學習交流扣扣群:1093794329,我自己整理的最新的前端資料和高級開發(fā)教程,如果有想需要的,可以加群一起學習交流
那么什么叫抽象方法呢?所有的普通方法上面都會有一個“{}”,這個表示方法體,有方法體的方法一定可以被對象直接使用。而抽象方法,是指沒有方法體的方法,同時抽象方法還必須使用關(guān)鍵字abstract做修飾。而擁有抽象方法的類就是抽象類,抽象類要使用abstract關(guān)鍵字聲明。
抽象類已經(jīng)實現(xiàn)的方法是為了代碼復(fù)用,待實現(xiàn)的方法是為了限制子類的功能。
定義一個抽象類
/*定義一個抽象類*/
abstract class AbstractMessage{
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessage(String info) {
this.infoString = info;
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
使用抽象類
首先,我們直接實例化抽象類的對象,看下是否可以直接進行實例化抽象類,代碼示例如下。
abstract class AbstractMessage{
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessage(String info) {
this.infoString = info;
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
public class Students {
public static void main(String[] args) {
System.out.println();
AbstractMessage messageInfo = new AbstractMessage("芝蘭生于深谷,不以無人而不芳\r\n" + "君子修身養(yǎng)德,不以窮困而改志") ;
messageInfo.send();
}
}
運行上述代碼,通過如下結(jié)果可知,AbstractMessage抽象類是無法直接進行實例化操作。
Error:(21, 39) java: abstractMessage是抽象的; 無法實例化
那么為什么無法被直接實例化呢,試想當一個類實例化之后,那么可以通過對象調(diào)用類的屬性或方法,但由于抽象方法并沒有方法體,因此無法進行調(diào)用。既然無法進行方法調(diào)用的話,又怎么去產(chǎn)生實例化對象呢。
抽象類的使用約束:
抽象類不能直接實例化,抽象類必須有子類,使用extends繼承,一個子類只能繼承一個抽象類,需要依靠子類采用向上轉(zhuǎn)型的方式處理;
抽象方法必須為public或者protected,因為如果為private,則不能被子類繼承,子類便無法實現(xiàn)該方法,當缺省情況下默認為public;
子類(不是抽象類)必須覆寫抽象類之中的全部抽象方法;
代碼示例如下:
public class Lian {
public static void main(String[] args) {
System.out.println();
/*向上轉(zhuǎn)型*/
AbstractMessage messageInfo = new message("芝蘭生于深谷,不以無人而不芳\r\n" + "君子修身養(yǎng)德,不以窮困而改志") ;
messageInfo.send();
}
}
abstract class AbstractMessage{
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessage(String info) {
this.infoString = info;
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
/*message類是抽象類的子類,是普通類*/
class message extends AbstractMessage {
public message(String info) {
super(info); //抽象類存在有參構(gòu)造方法,子類必須明確調(diào)用有參構(gòu)造。
}
/*強制要求覆寫*/
@Override
public void send() {
System.out.println("發(fā)送信息\n"+super.getInfo());
}
}
運行結(jié)果如下:
發(fā)送信息
芝蘭生于深谷,不以無人而不芳
君子修身養(yǎng)德,不以窮困而改志
通過如上運行結(jié)果,可以發(fā)現(xiàn):
繼承抽象類的子類必須覆寫抽象方法,而繼承普通類的子類可以選擇性的覆寫其中方法;
抽象類較普通類而言,多了抽象方法,其他組成部分和普通類一樣,普通類對象可以直接進行實例化,但抽象類的對象必須通過子類向上轉(zhuǎn)型進行實例化。
抽象類中允許有構(gòu)造方法?
由于抽象類里會存在一些屬性,那么抽象類中一定存在構(gòu)造方法,其存在目的是為了屬性的初始化。 并且子類對象實例化的時候,依然滿足先執(zhí)行父類構(gòu)造,再執(zhí)行子類構(gòu)造的順序。
范例如下:
public class Lian {
public static void main(String[] args) {
System.out.println();
/*向上轉(zhuǎn)型*/
AbstractMessage messageInfo = new message("芝蘭生于深谷,不以無人而不芳\r\n" + "君子修身養(yǎng)德,不以窮困而改志") ;
messageInfo.send();
}
}
abstract class AbstractMessage{
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessage(String info) {
this.infoString = info;
System.out.println("abstractMessage 構(gòu)造方法");
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
/*message類是抽象類的子類,是普通類*/
class message extends AbstractMessage {
/*抽象類存在有參構(gòu)造方法,子類必須明確調(diào)用有參構(gòu)造。*/
public message(String info) {
super(info);
System.out.println("message 構(gòu)造方法");
}
/*強制要求覆寫*/
@Override
public void send() {
System.out.println("發(fā)送信息\n"+super.getInfo());
}
}
執(zhí)行結(jié)果:
abstractMessage 構(gòu)造方法
message 構(gòu)造方法
發(fā)送信息
芝蘭生于深谷,不以無人而不芳
君子修身養(yǎng)德,不以窮困而改志
抽象類允許使用final聲明?
因為抽象類必須有子類,而final定義的類不能有子類,因此抽象類運行不能final聲明。
抽象類允許使用static聲明?
如下一個外部抽象類的示例:
public class Lian {
public static void main(String[] args) {
System.out.println();
/*向上轉(zhuǎn)型*/
AbstractMessage messageInfo = new message("芝蘭生于深谷,不以無人而不芳\r\n" + "君子修身養(yǎng)德,不以窮困而改志") ;
messageInfo.send();
}
}
static ?abstract class AbstractMessage{
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessage(String info) {
this.infoString = info;
System.out.println("abstractMessage 構(gòu)造方法");
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
/*message類是抽象類的子類,是普通類*/
class message extends abstractMessage {
/*抽象類存在有參構(gòu)造方法,子類必須明確調(diào)用有參構(gòu)造。*/
public message(String info) {
super(info);
System.out.println("message 構(gòu)造方法");
}
/*強制要求覆寫*/
@Override
public void send() {
System.out.println("發(fā)送信息\n"+super.getInfo());
}
}
Error:(12, 18) java: 此處不允許使用修飾符static
再看一個關(guān)于內(nèi)部抽象類:
public class Lain {
public static void main(String[] args) {
System.out.println();
/*向上轉(zhuǎn)型*/
AbstractMessage.AbstractMessageChild messageInfo = new message("芝蘭生于深谷,不以無人而不芳\r\n" + "君子修身養(yǎng)德,不以窮困而改志") ;
messageInfo.send();
}
}
abstract class AbstractMessage{
static abstract class AbstractMessageChild{//static定義的內(nèi)部類屬于外部類
/*提供setter getter*/
private String infoString ;
/*構(gòu)造方法*/
public AbstractMessageChild(String info) {
this.infoString = info;
System.out.println("abstractMessageChild 構(gòu)造方法");
}
/*普通方法*/
public String getInfo() {
return this.infoString;
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
}
/*message類是抽象類的子類,是普通類*/
class message extends AbstractMessage.AbstractMessageChild {
/*抽象類存在有參構(gòu)造方法,子類必須明確調(diào)用有參構(gòu)造。*/
public message(String info) {
super(info);
System.out.println("message 構(gòu)造方法");
}
/*強制要求覆寫*/
@Override
public void send() {
System.out.println("發(fā)送信息\n"+super.getInfo());
}
}
執(zhí)行結(jié)果如下:
abstractMessageChild 構(gòu)造方法
message 構(gòu)造方法
發(fā)送信息
芝蘭生于深谷,不以無人而不芳
君子修身養(yǎng)德,不以窮困而改志
由此可見,外部抽象類不允許使用static聲明,而內(nèi)部的抽象類運行使用static聲明。使用static聲明的內(nèi)部抽象類相當于一個外部抽象類,繼承的時候使用“外部類.內(nèi)部類”的形式表示類名稱。
可以直接調(diào)用抽象類中用static聲明的方法么? 任何時候,如果要執(zhí)行類中的static方法的時候,都可以在沒有對象的情況下直接調(diào)用,對于抽象類也一樣。 范例如下:
public class Lain {
public static void main(String[] args) {
abstractMessage.getInfo();
}
}
abstract class AbstractMessage{
/*靜態(tài)方法*/
public static void getInfo() {
System.out.println("芝蘭生于深谷,不以無人而不芳\r\n君子修身養(yǎng)德,不以窮困而改志");
}
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
}
/*message類是抽象類的子類,是普通類*/
class message extends AbstractMessage {
/*強制要求覆寫*/
@Override
public void send() {
System.out.println("發(fā)送信息\n");
}
}
運行結(jié)果:
芝蘭生于深谷,不以無人而不芳
君子修身養(yǎng)德,不以窮困而改志
(5)有時候由于抽象類中只需要一個特定的系統(tǒng)子類操作,所以可以忽略掉外部子類。這樣的設(shè)計在系統(tǒng)類庫中會比較常見,目的是對用戶隱藏不需要知道的子類。 范例如下:
public class Lain {
public static void main(String[] args) {
AbstractMessage abstractMessage = AbstractMessage.getInstance();
abstractMessage.send();
}
}
abstract class AbstractMessage{
/*抽象方法,沒有方法體,有abstract關(guān)鍵字做修飾*/
public abstract void send() ;
/*靜態(tài)方法*/
public static void getInfo() {
System.out.println("芝蘭生于深谷,不以無人而不芳\r\n君子修身養(yǎng)德,不以窮困而改志");
}
/*內(nèi)部抽象類子類*/
private static class AbstractMessageChild extends AbstractMessage{//內(nèi)部抽象類子類
public void send(){//覆寫抽象類的方法
System.out.println("發(fā)送信息 !");
}
}
/*靜態(tài)方法*/
public static AbstractMessage getInstance(){
return new AbstractMessageChild();
}
}
運行結(jié)果:
發(fā)送信息 !
抽象類之模板設(shè)計模式
模板方法模式:在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某些步驟。模板方法模式是基于繼承的代碼復(fù)用基本技術(shù),模板方法模式的結(jié)構(gòu)和用法也是面向?qū)ο笤O(shè)計的核心之一。在模板方法模式中,可以將相同的代碼放在父類中,而將不同的方法實現(xiàn)放在不同的子類中。
在模板方法模式中,我們需要準備一個抽象類,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實現(xiàn),然后聲明一些抽象方法來讓子類實現(xiàn)剩余的邏輯。不同的子類可以以不同的方式實現(xiàn)這些抽象方法,從而對剩余的邏輯有不同的實現(xiàn),這就是模板方法模式的用意。模板方法模式體現(xiàn)了面向?qū)ο蟮闹T多重要思想,是一種使用頻率較高的模式。
例如,現(xiàn)在有如下三類事務(wù):
機器人:充電、工作;
人:吃飯、工作、睡覺;
豬:吃飯、睡覺;
現(xiàn)要求實現(xiàn)一個程序, 通過抽象類定義并實現(xiàn)一個模板方法。這個模板方法定義了算法的骨架,而邏輯的組成步驟在相應(yīng)的抽象操作中,推遲到子類去實現(xiàn)可以實現(xiàn)三種不同事物的行為。
abstract class AbstractAction{
public static final int EAT = 1 ;
public static final int SLEEP = 3 ;
public static final int WORK = 5 ;
public abstract void eat();
public abstract void sleep();
public abstract void work();
public void commond(int flags){
switch(flags){
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
default:
break;
}
}
}
定義一個機器人的類,如下:
class Robot extends AbstractAction{
@Override
public void eat() {
System.out.println("機器人充電");
}
@Override
public void sleep() {
}
@Override
public void work() {
System.out.println("機器人工作");
}
}
定義一個人的類,如下:
class Person extends AbstractAction{
@Override
public void eat() {
System.out.println("人吃飯");
}
@Override
public void sleep() {
System.out.println("人睡覺");
}
@Override
public void work() {
System.out.println("人工作");
}
}
定義一個豬的類,如下:
class Pig extends AbstractAction{
@Override
public void eat() {
System.out.println("豬吃飯");
}
@Override
public void sleep() {
System.out.println("豬睡覺");
}
@Override
public void work() {
}
}
主類如下:
public class Students {
public static void main(String[] args) {
run(new Robot());
run(new Person());
run(new Pig());
}
public static void run(AbstractAction abstractAction){
abstractAction.commond(AbstractAction.EAT);
abstractAction.commond(AbstractAction.SLEEP);
abstractAction.commond(AbstractAction.WORK);
}
}
運行結(jié)果:
機器人充電
機器人工作
人吃飯
人睡覺
人工作
豬吃飯
豬睡覺
所有的子類如果要想正常的完成操作,必須按照指定的方法進行覆寫才可以,而這個時候抽象類所起的功能就是一個類定義模板的功能。
模板設(shè)計模式的優(yōu)缺點
模板方法模式通過把不變的行為搬移到超類,去除了子類中的重復(fù)代碼。子類實現(xiàn)算法的某些細節(jié),有助于算法的擴展。通過一個父類調(diào)用子類實現(xiàn)的操作,通過子類擴展增加新的行為,符合“開放-封閉原則”。 2.)缺點 每個不同的實現(xiàn)都需要定義一個子類,這會導致類的個數(shù)的增加,設(shè)計更加抽象。 3.)適用場景 在某些類的算法中,用了相同的方法,造成代碼的重復(fù)。控制子類擴展,子類必須遵守算法規(guī)則。
總結(jié)
以上是生活随笔為你收集整理的java 抽象属性 设计_Java 抽象类与模板设计模式详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql workbench crow
- 下一篇: java消费者和生产者模型_Java实现