欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java大話之創(chuàng)建型設(shè)計(jì)模式教程示例

 更新時(shí)間:2023年02月06日 16:03:56   作者:流浪漢kylin  
這篇文章主要為大家介紹了java大話之創(chuàng)建型設(shè)計(jì)模式教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

本文針對(duì)一些基礎(chǔ)的知識(shí)進(jìn)行一下總結(jié)。

創(chuàng)建型模式相對(duì)其它兩種模式也比較簡(jiǎn)單,用的地方也會(huì)更多,理解起來也會(huì)相對(duì)更容易,所以可以放在一起一次性講完。

1. 原型模式

沒想到吧,我不從單例開始講,當(dāng)然要從最簡(jiǎn)單的開始講,原型模式是干嘛的呢?通俗的講就是拷貝

我已經(jīng)有一個(gè)對(duì)象了,我要改這個(gè)對(duì)象的參數(shù),但是我又不能直接改,因?yàn)槠渌胤揭惨玫搅诉@個(gè)對(duì)象,我直接改的話其它地方的引用就有問題,那我只能創(chuàng)建一個(gè)一模一樣的對(duì)象,然后在修改。那怎么做呢,總不能創(chuàng)建一個(gè)對(duì)象然后根據(jù)前一個(gè)對(duì)象一個(gè)一個(gè)屬性賦值吧?這時(shí)候就需要用原型模式了

原型模式在java中的實(shí)現(xiàn)是繼承Cloneable接口然后實(shí)現(xiàn)clone()方法

public class Test implements Cloneable{
    public String name;
    public int age;
    public Object testObj;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

調(diào)用時(shí)

Test testA = new Test();
try {
    Test testB = (Test) testA.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

看得出很簡(jiǎn)單,也很容易理解,也很常用。
除此之外,它還有一個(gè)比較重要的知識(shí)點(diǎn)就是深拷貝和淺拷貝

有什么區(qū)別呢?簡(jiǎn)單來說就是內(nèi)部的對(duì)象參數(shù)也是拷貝的對(duì)象,還是指向同一個(gè)地址的同一個(gè)對(duì)象。
上面的Demo就是淺拷貝,要實(shí)現(xiàn)深拷貝的話就要自己實(shí)現(xiàn)clone方法的具體操作,比如(偽代碼,大概能看懂就行)

public class Test implements Cloneable {
    public String name;
    public int age;
    public Object testObj;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Test testB = (Test) super.clone();
        Object newObj = new Object();
        newObj.xxx = testObj.xxx;
        testB.testObj = newObj;
        return testB;
    }
}

2. 建造者模式

又稱為builder模式,主要使用場(chǎng)景是一個(gè)對(duì)象有多個(gè)參數(shù)的時(shí)候,而且這些參數(shù)可傳可不傳,不傳的話就用默認(rèn)值。

這種情況下,如果你用構(gòu)造參數(shù)來做,你不知道要寫多少個(gè)構(gòu)造參數(shù),你用set方法來做,你就要寫很多行set操作,而且不美觀。這時(shí)候就需要用到builder模式,它是基于一個(gè)鏈?zhǔn)秸{(diào)用的方法,寫起來很美觀。

public class Test {
    public Test(Builder builder) {
    }
    public static class Builder {
        private Context context;
        private String name = "";
        private int age = 18;
        private int sex = 0;
        private String phone = "";
        public Builder(Context context) {
            this.context = context;
        }
        public Builder setName(String name) {
            this.name = name;
            return this;
        }
        public Builder setAge(int age) {
            this.age = age;
            return this;
        }
        public Builder setSex(int sex) {
            this.sex = sex;
            return this;
        }
        public Builder setPhone(String phone) {
            this.phone = phone;
            return this;
        }
        public Test build() {
            return new Test(this);
        }
    }
}

大概這樣,然后調(diào)用的時(shí)候

Test testA = new Test.Builder(this)
        .setName("name")
        .setAge(16)
        .setSex(1)
        .setPhone("phone")
        .build();

這樣的鏈?zhǔn)秸{(diào)用看起來就比較美觀,如果你只想傳部分參數(shù)

Test testA = new Test.Builder(this)
        .setName("name")
        .build();

看得出很簡(jiǎn)單,也很容易理解,也很常用。
實(shí)用?嗯...... 準(zhǔn)確來說,應(yīng)該是對(duì)java來說比較實(shí)用,但如果你是用kotlin的話,用data更爽。

我個(gè)人還有個(gè)習(xí)慣是如果參數(shù)少于5個(gè),我都是用構(gòu)造方法來做,如果超過4個(gè),我才考慮用Builder

3. 工廠模式

工廠模式簡(jiǎn)單來說就算抽象一個(gè)工廠,你創(chuàng)建對(duì)象的操作就交給這個(gè)工廠來處理。使用的場(chǎng)景也比較廣泛,我個(gè)人使用比較多的場(chǎng)景是和業(yè)務(wù)邏輯掛鉤的,受業(yè)務(wù)的影響導(dǎo)致有些對(duì)象我沒辦法復(fù)用,不同的業(yè)務(wù)分支要?jiǎng)?chuàng)建不同的業(yè)務(wù)對(duì)象,我就會(huì)用工廠來管理創(chuàng)建的邏輯,這樣以后要改或者怎樣的時(shí)候去改工廠這個(gè)對(duì)象就行,還是很方便的。

工廠模式又分為幾種,簡(jiǎn)單工廠、工廠方法和抽象工廠,我這里只講簡(jiǎn)單工廠。為什么呢?因?yàn)槟阋喇?dāng)簡(jiǎn)單工廠的創(chuàng)建邏輯超復(fù)雜導(dǎo)致很臃腫的時(shí)候(或在用我的話來說創(chuàng)建的邏輯有多個(gè)維度的時(shí)候),會(huì)用到工廠方法和抽象工廠,可以簡(jiǎn)單理解成他們是簡(jiǎn)單工廠的升級(jí)版本。

我這里先拿個(gè)別人的Demo來舉個(gè)例子

public interface Shape {
    void draw(); 
}
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

定義了這些對(duì)象,然后寫個(gè)工廠來管理創(chuàng)建的流程

public class ShapeFactory {
    public Shape getShape(String shapeType){
        if(shapeType == null){
            return null;
        }
        if(shapeType.equalsIgnoreCase("CIRCLE")){
            return new Circle();
        } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
            return new Rectangle();
        }
        return null;
    }
}

重點(diǎn)在于ShapeFactory這個(gè)類,有這么一個(gè)工廠類的概念,工廠是一個(gè)抽象,工廠里面提供相對(duì)應(yīng)的方法來寫創(chuàng)建的邏輯。

工廠基本不會(huì)復(fù)用,因?yàn)樗锩娴膭?chuàng)建邏輯都是和業(yè)務(wù)邏輯相關(guān)的,所以在復(fù)雜的情況中,不光會(huì)只寫if-else或者switch。那這里我可以拋出一個(gè)問題,如果這個(gè)工廠創(chuàng)建對(duì)象時(shí),有些對(duì)象是同步創(chuàng)建,有些對(duì)象是異步創(chuàng)建,你會(huì)怎么處理?

4. 單例模式

什么時(shí)候會(huì)使用到單例,簡(jiǎn)單來說就是全局共用一個(gè)對(duì)象的時(shí)候,那么明顯可以看出它的生命周期很長(zhǎng),所以很容易知道它有個(gè)缺點(diǎn),很容易造成內(nèi)存泄露 ,比如你在這個(gè)單例里面存了很多全局變量又不釋放,那就會(huì)內(nèi)存泄露。

單例又分為懶漢模式和俄漢模式

// 懶漢
public class Test {
    private Test(){}
    private static Test instance = null;
    public static Test getInstance(){
        if (instance == null){
            instance = new Test();
        }
        return instance;
    }
}
// 餓漢
public class Test {
    private Test(){}
    private static final Test instance = new Test();
    public static Test getInstance(){
        return instance;
    }
}

區(qū)別是餓漢在類加載的時(shí)候?qū)ο缶蜁?huì)創(chuàng)建出來,懶漢是在第一次調(diào)用的時(shí)候?qū)ο蟊粍?chuàng)建出來。餓漢是線程安全的,懶漢是線程不安全的,所以我們一般在多線程的環(huán)境中使用懶漢的話要通過一些方式保證線程安全。

這里有兩種方法來保證線程安全,雙重檢鎖和靜態(tài)內(nèi)部類。

// 雙重檢鎖
public class Test {
    private static volatile Test mTest = null;
    private Test() {
    }
    public static Test getInstance() {
        if (mTest == null) {
            synchronized (Test.class) {
                if (mTest == null) {
                    mTest = new Test();
                }
            }
        }
        return mTest;
    }
}

相信都能一眼看懂什么意思,唯一注意的是要加volatile來保證有序性,因?yàn)閚ew Test()不是一個(gè)原子性操作。

// 靜態(tài)內(nèi)部類
public class Test {
    private static class LazyHolder{
        private static final Test INSTANCE = new Test();
    }
    private Test(){}
    public static final Test getInstance(){
        return LazyHolder.INSTANCE;
    }
}

這是通過使用類加載機(jī)制來保證對(duì)象只創(chuàng)建一次從而保證線程安全。 這兩種方法都可以保證線程安全,兩種方法都可以使用,但我更傾向于雙檢鎖,因?yàn)槟苁∪ヒ徊筋惣虞d,雖然這個(gè)影響不大。

5. 總結(jié)

創(chuàng)建型模式主要是為了解決創(chuàng)建對(duì)象時(shí)的場(chǎng)景而被設(shè)計(jì)出來的,原型模式是為了處理復(fù)制對(duì)象的情況,建造者模式是為了處理創(chuàng)建對(duì)象時(shí)靈活傳參的情況,工廠模式是為了處理創(chuàng)建對(duì)象的邏輯,單例模式是為了處理全局共用一個(gè)對(duì)象的情況。

相信看到這里相信都能了解創(chuàng)建型模式的概念和其中各個(gè)模式的使用。好了,正文開始,我的總結(jié)主要是想做一個(gè)反推,這些東西是怎么被設(shè)計(jì)出來的,無非就是同個(gè)場(chǎng)景的代碼敲多了,然后進(jìn)行總結(jié),設(shè)計(jì)出一套東西來方便這個(gè)場(chǎng)景的開發(fā)。

比如想象一下沒有單例時(shí)會(huì)怎么去實(shí)現(xiàn)單例的功能。(或者說怎么使用low一點(diǎn)的方法來實(shí)現(xiàn)單例效果),如果你讓我來做,我可能會(huì)想到通過序列化來實(shí)現(xiàn),當(dāng)需要多個(gè)地方改同一個(gè)對(duì)象的某個(gè)屬性時(shí)(不考慮多線程的情況),把這個(gè)對(duì)象序列化本地,反序列化改屬性之后再序列化回去,然后把這套東西封裝起來,這也能實(shí)現(xiàn)單例的效果,但是這樣一比就會(huì)發(fā)現(xiàn)單例的解決方案比這個(gè)方便得多,所以才需要學(xué)習(xí)設(shè)計(jì)模式。

以上就是java大話之創(chuàng)建型設(shè)計(jì)模式教程示例的詳細(xì)內(nèi)容,更多關(guān)于java創(chuàng)建型設(shè)計(jì)模式 的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringMVC的執(zhí)行過程淺析

    SpringMVC的執(zhí)行過程淺析

    這篇文章主要給大家介紹了關(guān)于SpringMVC的執(zhí)行過程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用SpringMVC具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 深入理解JVM自動(dòng)內(nèi)存管理

    深入理解JVM自動(dòng)內(nèi)存管理

    對(duì)于Java虛擬機(jī)在內(nèi)存分配與回收的學(xué)習(xí),本文主要介紹了JVM自動(dòng)內(nèi)存管理,文中通過圖文示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Java參數(shù)校驗(yàn)詳解之使用@Valid注解和自定義注解進(jìn)行參數(shù)驗(yàn)證

    Java參數(shù)校驗(yàn)詳解之使用@Valid注解和自定義注解進(jìn)行參數(shù)驗(yàn)證

    在后端開發(fā)中,參數(shù)校驗(yàn)是非常普遍的,下面這篇文章主要給大家介紹了關(guān)于Java參數(shù)校驗(yàn)詳解之使用@Valid注解和自定義注解進(jìn)行參數(shù)驗(yàn)證的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • 如何使用JDBC連接數(shù)據(jù)庫(kù)并執(zhí)行SQL語(yǔ)句

    如何使用JDBC連接數(shù)據(jù)庫(kù)并執(zhí)行SQL語(yǔ)句

    JDBC是Java數(shù)據(jù)庫(kù)連接的縮寫,是Java程序與數(shù)據(jù)庫(kù)進(jìn)行交互的標(biāo)準(zhǔn)API。JDBC主要包括Java.sql和javax.sql兩個(gè)包,通過DriverManager獲取數(shù)據(jù)庫(kù)連接對(duì)象Connection,并通過Statement或PreparedStatement執(zhí)行SQL語(yǔ)句
    2023-04-04
  • 運(yùn)行jar程序時(shí)添加vm參數(shù)的方法

    運(yùn)行jar程序時(shí)添加vm參數(shù)的方法

    下面小編就為大家?guī)硪黄\(yùn)行jar程序時(shí)添加vm參數(shù)的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • log4j2 RollingRandomAccessFile配置過程

    log4j2 RollingRandomAccessFile配置過程

    這篇文章主要介紹了log4j2 RollingRandomAccessFile配置過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring Cloud Stream微服務(wù)消息框架原理及實(shí)例解析

    Spring Cloud Stream微服務(wù)消息框架原理及實(shí)例解析

    這篇文章主要介紹了Spring Cloud Stream微服務(wù)消息框架原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 淺談java Collection中的排序問題

    淺談java Collection中的排序問題

    下面小編就為大家?guī)硪黄獪\談java Collection中的排序問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • Spring實(shí)戰(zhàn)之獲取其他Bean的屬性值操作示例

    Spring實(shí)戰(zhàn)之獲取其他Bean的屬性值操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之獲取其他Bean的屬性值操作,結(jié)合實(shí)例形式分析了Spring操作Bean屬性值的相關(guān)配置與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-12-12
  • javascript與jsp發(fā)送請(qǐng)求到servlet的幾種方式實(shí)例

    javascript與jsp發(fā)送請(qǐng)求到servlet的幾種方式實(shí)例

    本文分別給出了javascript發(fā)送請(qǐng)求到servlet的5種方式實(shí)例與 jsp發(fā)送請(qǐng)求到servlet的6種方式實(shí)例
    2018-03-03

最新評(píng)論