成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

抽象類(lèi)和模板方法模式

only_do / 600人閱讀

摘要:抽象類(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

相關(guān)文章

  • 7. 初步理解面向?qū)ο?【連載 7】

    摘要:是一種典型的面向?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);...

    keelii 評(píng)論0 收藏0
  • 抽象類(lèi)和接口的區(qū)別

    摘要:抽象類(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...

    ThinkSNS 評(píng)論0 收藏0
  • java抽象類(lèi)和接口總結(jié)

    摘要:如果一個(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)...

    荊兆峰 評(píng)論0 收藏0
  • Java抽象類(lèi)與接口的區(qū)別

    摘要:很多常見(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)...

    Ethan815 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<