Java代碼複用的三種經常使用方式:繼承、組合和代理

複用代碼是Java衆多引人注目的功能之一。這句話很通順,沒什麼問題,但問題在於不少人並不清楚「複用」是什麼。就好像我說「沉默王二是一個不止會寫代碼的程序員」,唉,沉默王二是誰?程序員

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,裏面有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。分佈式

咱們須要來給「複用」下一個定義。複用,說白了就是重複使用。微服務

舉個例子,不少名人說了不少名言,咱們在說話、寫做的時候,就常常有意無心的重複這些名言。好比說我,就特別喜歡重複使用王小波的那句名言:「從話語中,你不多能學到人性,從沉默中卻能。假如還想學得更多,那就要繼續一聲不吭 。」源碼分析

上面這個例子,只能說是「複用」的一種低級的應用,其實就是複製粘貼了。還有高級的複用方式嗎?性能

有,固然有。Java做爲一種優秀的面向對象設計的語言,在複用的應用上就高級得多了。學習

01 繼承

最多見的複用方法就是繼承——使用extends關鍵字在基類的基礎上建立新類,新類能夠直接複用基類的非private的屬性和方法;就像程序清單1-1那樣。this

程序清單1-1:spa

public class Wangxiaosan extends Wangsan {
    public Wangxiaosan() {
        System.out.println("我是新類王小三");

        setName("王老三");

        System.out.println(getName());
    }

    public static void main(String[] args) {
        new Wangxiaosan();
    }
}

class Wangsan {
    private String name;

    Wangsan() {
        System.out.println("我是基類王三");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

從程序清單1-1中咱們能夠看得出,getName()和setName()方法雖然是在基類Wangsan中建立的,但能夠在新類Wangxiaosan中使用,代碼的複用工做就這樣輕鬆地完成了。設計

02 組合

另一種常見的複用方法就是組合——在新類中建立已有類的對象,經過該對象來調用已有類中的非private的屬性和方法;就像程序清單2-1那樣。代理

程序清單2-1:

public class Tongxiangyu {
    private Baizhantang boyFriend = new Baizhantang();

    public Tongxiangyu() {
        System.out.println("我是同福客棧的掌櫃佟湘玉");

        boyFriend.pointHand("郭芙蓉");
    }

    public static void main(String[] args) {
        new Tongxiangyu();
    }
}

class Baizhantang {
    Baizhantang() {
        System.out.println("我是退隱江湖的盜聖白展堂");
    }

    public void pointHand(String name) {
        System.out.println("那誰" + name + ",準備一下——葵花點穴手");
    }
}

從程序清單2-1中咱們能夠看得出,葵花點穴手雖然是白展堂的絕技,但做爲佟掌櫃的男友,佟掌櫃要展堂點個穴,展堂也是不敢辭讓的。你看,佟掌櫃雖然是個弱女子,但自從有了展堂這個武功首屈一指的男友,再沒有誰敢不聽話啊——厲害的組合啊。

須要注意的是,如何在繼承和組合之間作出選擇呢?

若是新類和已有類須要具備一些類似的方法和屬性時,就採用繼承的形式;若是新類只是爲了借用已有類的一些方法和屬性時,而二者沒有不少類似之處時就須要採用組合的形式。

03 代理

還有一種複用方法是代理——在新類中建立代理,經過代理來操做已有類的非private的屬性和方法;就像程序清單3-1那樣。

程序清單3-1:

public class Member {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        System.out.println("代理說一個藥丸十五塊");
        proxy.buy(15);
    }
}

class Proxy {
    private Shop shop = new Shop();

    public void buy(int money) {
        System.out.println("一個藥丸十五塊");
        shop.sale(money - 5);
    }
}

class Shop {
    public void sale(int money) {
        System.out.println("一個藥丸十塊錢");
    }
}

從程序清單3-1中咱們能夠看得出,代理的模式和組合有點相似,但又有差異——代理成功的隔開了新類(會員)和已有類(店鋪)的直接關係,使得已有類的方法不直接暴露在新類面前(組合的方式會將已有類的非private的方法和屬性直接暴露在新類中);與此同時,代理拿到了足夠的好處。

04 final

做爲代碼的生產者來講,咱們有時候但願代碼被複用,有的時候又但願代碼不被複用。當咱們不想代碼被複用時,final關鍵字就派上用場了。final這個關鍵字很形象,它自己就說明了一切——最後的,最終的;決定性的;不可更改的。

使用final的場景有三種,分別是數據、方法和類。咱們來稍做說明。

1)final 數據

最多見的final數據就是常量了,例如:

public class Consts {
    public static final String CMOWER = "沉默王二";
}

對於常量來講,它對於整個應用內的全部類都是可見的,所以是public的;它能夠直接經過類名.常量名訪問,因此是static的;它是不可修改的,所以是final的。

另一種常見的final數據就是參數了,參照程序清單4-1。

程序清單4-1:

public class Cmower {

    public void write(final String content) {
        // content += "猶未雪"; // final修飾的參數是沒法在方法內部被再次修改的
        System.out.println(content);
    }

    public void write1(String content) {
        content += "猶未雪";
        System.out.println(content);
    }

    public static void main(String[] args) {
        Cmower cmower = new Cmower();
        cmower.write("精忠報國");
        cmower.write1("靖康恥");
    }
}

2)final 方法

在Java類中,全部的private方法都隱式地指定爲final的(也就是說,若是你在private方法上加上final修飾符,實際上是沒啥意義的)。在介紹繼承的時候,你應該注意到我強調的一句話,就是新類能夠直接複用基類的非private的屬性和方法,也就是說private方法是沒法被繼承者修改的,由於private方法是final的。

來看程序清單4-2,你會發現Wangsan類型的san引用是不能調用say(String words)方法的,由於private方法是沒法被繼承者修改的,儘管Wangxiaosan中從新定義了say(String words)方法。

程序清單4-2:

public class Wangxiaosan extends Wangsan {
    public Wangxiaosan() {
        say("吃中飯沒");
    }

    public void say(String words) {
        System.out.println("王小三在說:" + words);
    }

    public static void main(String[] args) {
        Wangsan san = new Wangxiaosan();
        // san.say("吃晚餐沒"); // 沒法訪問,並不會被覆蓋
    }
}

class Wangsan {
    public Wangsan() {
        say("吃早飯沒");
    }

    private void say(String words) {
        System.out.println("王三在說:" + words);
    }
}

3)final 類

當咱們認爲某個類就是最終的形態了,它很完美,不該該被繼承,就可使用final關鍵字來修飾;參照程序清單4-3。

程序清單4-3:

// 沒法繼承
public class Wangxiaosan extends Wangsan {
}

final class Wangsan {
    public Wangsan() {
        System.out.println("我就是最終形態,別繼承我!");
    }
}
相關文章
相關標籤/搜索