摘要:抽象類(lèi)作為多個(gè)子類(lèi)的通用模板,子類(lèi)在抽象類(lèi)的基礎(chǔ)上進(jìn)行擴(kuò)展改造,但子類(lèi)總體上會(huì)大致保留抽象類(lèi)的行為方式。稍微專(zhuān)業(yè)一點(diǎn)的定義就是模板方法模式,在一個(gè)方法中定義一個(gè)算法的骨架,而將一些步驟延遲到子類(lèi)中。
抽象方法和抽象類(lèi)
抽象類(lèi):用abstract修飾符修飾的類(lèi),如:
public abstract class GeneralService { }
抽象方法:用abstract修飾符修飾的方法,抽象方法不能有方法體,如:
public abstract void service();
抽象類(lèi)和抽象方法的規(guī)則如下:
必須用abstract修飾符修飾
抽象類(lèi)不一定包含抽象方法,但含有抽象方法的類(lèi)一定是抽象類(lèi)
抽象類(lèi)不能被實(shí)例化
抽象類(lèi)的構(gòu)造器不能用于創(chuàng)建對(duì)象,主要是用于被其子類(lèi)調(diào)用
下面定義一個(gè)Shape抽象類(lèi):
/** * 定義一個(gè)抽象類(lèi),用于描述抽象概念的“形狀” */ public abstract class Shape { // 形狀的 顏色 private String color; public String getColor() { return color; } public void setColor(String color) { this.color = color; } // 帶參構(gòu)造器 public Shape(String color) { this.color = color; } // 定義一個(gè)計(jì)算周長(zhǎng)的抽象方法 public abstract double calPerimeter(); }
上面的Shape類(lèi)中包含了一個(gè)抽象方法calPerimeter(),所以Shape類(lèi)只能是抽象類(lèi)。Shape類(lèi)中既包含初始化塊,又包含構(gòu)造器,不過(guò)這些都不是在創(chuàng)建Shape對(duì)象時(shí)被調(diào)用的,而是在創(chuàng)建其子類(lèi)對(duì)象時(shí)被調(diào)用。
下面定義一個(gè)Triangle類(lèi)和一個(gè)Circle類(lèi),讓他們繼承Shape類(lèi),并實(shí)現(xiàn)Shape中的抽象方法calPerimeter()。
/** * 定義一個(gè)三角形類(lèi),繼承自形狀類(lèi) */ public class Triangle extends Shape { // 定義三角形的三條邊 private double a; private double b; private double c; public Triangle(String color, double a, double b, double c) { super(color); this.a = a; this.b = b; this.c = c; } @Override public double calPerimeter() { return a + b + c; } }
/** * 定義一個(gè)圓形類(lèi),繼承自形狀類(lèi) */ public class Circle extends Shape { // 定義圓的半徑 private double radius; public Circle(String color, double radius) { super(color); this.radius = radius; } @Override public double calPerimeter() { return 2 * Math.PI * this.radius; } }
Shape(形狀)類(lèi)是一個(gè)抽象的概念,Triangle(三角形)類(lèi)和Circle(圓形)類(lèi)是Shape的具象,它們都各自實(shí)現(xiàn)了Shape的calPerimeter()方法,兩者計(jì)算周長(zhǎng)的公式不一樣。
下面是測(cè)試類(lèi):
/** * 測(cè)試類(lèi) */ public class Test { public static void main(String[] args) { Shape s1 = new Triangle("黃色", 3.0, 4.0, 5.0); Shape s2 = new Circle("紅色", 3); System.out.println("三角形s1的顏色:" + s1.getColor() + ",周長(zhǎng):" + s1.calPerimeter()); System.out.println("圓形s2的顏色:" + s2.getColor() + ",周長(zhǎng):" + s2.calPerimeter()); } }
輸出結(jié)果:
三角形s1的顏色:黃色,周長(zhǎng):12.0 圓形s2的顏色:紅色,周長(zhǎng):18.84955592153876
當(dāng)使用abstract修飾類(lèi)時(shí),表明這個(gè)類(lèi)是抽象類(lèi),只能被繼承;當(dāng)使用abstract修飾方法時(shí),表明這個(gè)方法必須由其子類(lèi)實(shí)現(xiàn)(重寫(xiě))。
final修飾的類(lèi)不能被繼承,final修飾的方法不能被重寫(xiě),因此final和abstract不能同時(shí)使用。
當(dāng)使用static修飾一個(gè)方式時(shí),表示這個(gè)方法是類(lèi)方法,可以通過(guò)類(lèi)直接調(diào)用而無(wú)需創(chuàng)建對(duì)象。但如果該方法被定義成抽象的,則將導(dǎo)致通過(guò)該類(lèi)來(lái)調(diào)用該方法時(shí)出現(xiàn)錯(cuò)誤(調(diào)用了一個(gè)沒(méi)有方法體的方法肯定會(huì)引起錯(cuò)誤),因此,static和abstract不能同時(shí)修飾某個(gè)方法。
abstract關(guān)鍵字修飾的方法必須由其子類(lèi)重寫(xiě)才有意義,因此abstract方法不能定義成private訪(fǎng)問(wèn)權(quán)限,即private和abstract不能同時(shí)修飾某個(gè)方法、
抽象類(lèi)的作用抽象類(lèi)是從多個(gè)具體類(lèi)中抽象出來(lái)的父類(lèi),它具有更高層次的抽象,描述了一組事物的共性。
抽象類(lèi)作為多個(gè)子類(lèi)的通用模板,子類(lèi)在抽象類(lèi)的基礎(chǔ)上進(jìn)行擴(kuò)展、改造,但子類(lèi)總體上會(huì)大致保留抽象類(lèi)的行為方式。
模板方法模式如果編寫(xiě)一個(gè)抽象父類(lèi),父類(lèi)提供了多個(gè)子類(lèi)的通用方法,并把一個(gè)或多個(gè)方法留給其子類(lèi)去實(shí)現(xiàn),這就是模板模式,是一種十分常見(jiàn)且簡(jiǎn)單的設(shè)計(jì)模式。
稍微專(zhuān)業(yè)一點(diǎn)的定義就是:
模板方法模式,在一個(gè)方法中定義一個(gè)算法的骨架,而將一些步驟延遲到子類(lèi)中。模板方法使得子類(lèi)可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某些步驟。
下面再介紹一個(gè)模板方法模式的范例,在這個(gè)范例中,我們把做菜這個(gè)過(guò)程分為三個(gè)步驟:
備料
烹制
裝盤(pán)
這三部就是算法的骨架。然而做不同的菜,需要備的料,烹制的方法,以及如何裝盤(pán)都是不同的,做不同的菜時(shí),需要有不一樣的實(shí)現(xiàn)。
先來(lái)寫(xiě)一個(gè)抽象的做菜父類(lèi),代碼如下:
/** * 定義做菜抽象類(lèi) */ public abstract class DodishTemplate { /** * 模板方法,封裝了做菜的算法 * 用final關(guān)鍵字進(jìn)行修飾,避免子類(lèi)修改算法的順序 * 模板方法定義了一連竄的步驟,每一個(gè)步驟由一個(gè)方法代表 */ protected final void dodish(){ this.preparation(); this.doing(); this.sabot(); } /** * 備料 */ public abstract void preparation(); /** * 烹制 */ public abstract void doing(); /** * 裝盤(pán) */ public abstract void sabot(); }
下面再定義做番茄炒蛋類(lèi)和做紅燒肉類(lèi)并實(shí)現(xiàn)父類(lèi)中的抽象方法:
/** * 做番茄炒蛋類(lèi) */ public class EggsWithTomato extends DodishTemplate{ @Override public void preparation() { System.out.println("洗并切西紅柿,打雞蛋。"); } @Override public void doing() { System.out.println("雞蛋倒入鍋里,然后倒入西紅柿一起炒。"); } @Override public void sabot() { System.out.println("將炒好的番茄炒蛋裝入碟子里,撒上香蔥。"); } }
/** * 做紅燒肉類(lèi) */ public class Bouilli extends DodishTemplate{ @Override public void preparation() { System.out.println("切豬肉和土豆。"); } @Override public void doing() { System.out.println("將切好的豬肉倒入鍋中炒一會(huì)然后倒入土豆連炒帶燉。"); } @Override public void sabot() { System.out.println("將做好的紅燒肉盛進(jìn)碗里,撒上白芝麻"); } }
在測(cè)試類(lèi)中我們來(lái)做菜:
public class App { public static void main(String[] args) { DodishTemplate eggsWithTomato = new EggsWithTomato(); eggsWithTomato.dodish(); System.out.println("-----------------------------"); DodishTemplate bouilli = new Bouilli(); bouilli.dodish(); } }
運(yùn)行結(jié)果:
洗并切西紅柿,打雞蛋。 雞蛋倒入鍋里,然后倒入西紅柿一起炒。 將炒好的番茄炒蛋裝入碟子里,撒上香蔥。 ----------------------------- 切豬肉和土豆。 將切好的豬肉倒入鍋中炒一會(huì)然后倒入土豆連炒帶燉。 將做好的紅燒肉盛進(jìn)碗里,撒上白芝麻
從這個(gè)案例我們可以看到,DodishTemplate類(lèi)里定義了做菜的通用算法,而一些具體的實(shí)現(xiàn)細(xì)節(jié)則推遲到了其子類(lèi)(EggsWithTomato和Bouilli)中。也就是說(shuō),模板方法定義了一個(gè)算法的步驟,并允許子類(lèi)為一個(gè)或多個(gè)步驟提供實(shí)現(xiàn)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74189.html
摘要:是一種典型的面向?qū)ο缶幊陶Z(yǔ)言。這篇文章主要是來(lái)初步理解一下面向?qū)ο蟮乃季S為下面的內(nèi)容先給一個(gè)基礎(chǔ)。針對(duì)面向?qū)ο缶幊痰母鄡?nèi)容,會(huì)在后面的文章里面詳細(xì)解釋。他們都稱(chēng)之為對(duì)象。之后,我們?cè)儆镁幊陶Z(yǔ)言,把這種映射編寫(xiě)出來(lái),就是的面向?qū)ο缶幊汤病? showImg(https://segmentfault.com/img/remote/1460000012983458?w=900&h=500);...
摘要:抽象類(lèi)是對(duì)整個(gè)類(lèi)整體進(jìn)行抽象,包括屬性行為,但是接口卻是對(duì)類(lèi)局部行為進(jìn)行抽象。因此最好的解決辦法是單獨(dú)將報(bào)警設(shè)計(jì)為一個(gè)接口,包含行為設(shè)計(jì)為單獨(dú)的一個(gè)抽象類(lèi),包含和兩種行為。 抽象類(lèi)和接口的區(qū)別 1.語(yǔ)法層面上的區(qū)別 1)抽象類(lèi)可以提供成員方法的實(shí)現(xiàn)細(xì)節(jié),而接口中只能存在public abstract 方法; 2)抽象類(lèi)中的成員變量可以是各種類(lèi)型的,而接口中的成員變量只能是pub...
摘要:如果一個(gè)非抽象類(lèi)遵循了某個(gè)接口,就必須實(shí)現(xiàn)該接口中的所有方法。抽象類(lèi)是對(duì)整個(gè)類(lèi)整體進(jìn)行抽象,包括屬性行為,但是接口卻是對(duì)類(lèi)局部行為進(jìn)行抽象。因此最好的解決辦法是單獨(dú)將報(bào)警設(shè)計(jì)為一個(gè)接口,包含行為設(shè)計(jì)為單獨(dú)的一個(gè)抽象類(lèi),包含和兩種行為。 一、抽象類(lèi) 二、接口 三、抽象類(lèi)和接口的區(qū)別 一、抽象類(lèi) 在了解抽象類(lèi)之前,先來(lái)了解一下抽象方法。抽象方法是一種特殊的方法:它只有聲明,而沒(méi)有具體的實(shí)現(xiàn)...
摘要:很多常見(jiàn)的面試題都會(huì)出諸如抽象類(lèi)和接口有什么區(qū)別,什么情況下會(huì)使用抽象類(lèi)和什么情況你會(huì)使用接口這樣的問(wèn)題。在討論它們之間的不同點(diǎn)之前,我們先看看抽象類(lèi)接口各自的特性。抽象類(lèi)抽象類(lèi)是用來(lái)捕捉子類(lèi)的通用特性的。 很多常見(jiàn)的面試題都會(huì)出諸如抽象類(lèi)和接口有什么區(qū)別,什么情況下會(huì)使用抽象類(lèi)和什么情況你會(huì)使用接口這樣的問(wèn)題。本文我們將仔細(xì)討論這些話(huà)題。 在討論它們之間的不同點(diǎn)之前,我們先看看抽象類(lèi)...
閱讀 2586·2021-11-25 09:43
閱讀 1863·2021-09-22 15:26
閱讀 3742·2019-08-30 15:56
閱讀 1714·2019-08-30 15:55
閱讀 1899·2019-08-30 15:54
閱讀 816·2019-08-30 15:52
閱讀 3158·2019-08-29 16:23
閱讀 897·2019-08-29 12:43