日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

activexobject对象不能创建_【设计模式】建造者模式:你创建对象的方式有它丝滑吗?...

發(fā)布時間:2025/4/17 asp.net 112 豆豆
生活随笔 收集整理的這篇文章主要介紹了 activexobject对象不能创建_【设计模式】建造者模式:你创建对象的方式有它丝滑吗?... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • 什么是建造者模式
  • 為什么要使用建造者模式
  • 構(gòu)造函數(shù)創(chuàng)建對象
  • set方式構(gòu)建對象
  • java實現(xiàn)建造者模式
    • 第一種實現(xiàn)方式
    • 第二種方式
  • 建造者模式與構(gòu)造函數(shù)的對比
  • 建造者模式與工廠模式的對比
  • 總結(jié)

什么是建造者模式

建造者模式是設(shè)計模式的一種,將一個復雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

其實建造者模式是被翻譯過來的,他原名叫builder模式,也被稱為生成器模式,這種模式的實現(xiàn)非常的簡單,只是在使用方面可能會有點摸不著方向,它主要解決復雜的對象創(chuàng)建,比如參數(shù)過長、校驗過多等等。

為什么要使用建造者模式

我們都知道,創(chuàng)建對象的方法有很多,new是我們最常見也是最熟悉的一種,我們?yōu)槭裁床皇褂梦覀冏钍煜さ亩x用建造者模式呢?雖然new是我們最熟悉的,但不一定是最合適的,為什么這么說呢?我們舉個例子來說明一下。

我們現(xiàn)在定義一個對象:ThreadConfig,ThreadConfig有5個屬性:核心線程數(shù)(corePoolSize)、最大線程數(shù)(maxPoolSize)、隊列數(shù)(queueCapacity)、空閑時間退出(keepAliveTime)、是否允許線程退出(allowCoreThreadTimeout)。屬性有必填、有選填。

屬性名必填默認值注釋threadName是

線程名corePoolSize否4核心線程數(shù)maxPoolSize是

核心線程數(shù)queueCapacity是

最大線程數(shù)keepAliveTime是

當線程空閑時間達到keepAliveTime,該線程會退出allowCoreThreadTimeout是

是否允許核心線程數(shù)空閑時退出

創(chuàng)建對象的時候要滿足以下要求:
1.最大線程數(shù)不傳,默認為核心線程數(shù)的大小。
2.最大線程數(shù)不能小于核心線程數(shù)。
3.如果填寫隊列數(shù),隊列書不能小于等于0。
4.如果填寫keepAliveTime,不能小于等于0。

看到這樣的一個對象,如果是你,你會怎么設(shè)計他的對象創(chuàng)建呢?

構(gòu)造函數(shù)創(chuàng)建對象

大家想到的第一種創(chuàng)建方式可能就是構(gòu)造函數(shù),那我們先使用構(gòu)造函數(shù)實現(xiàn)一下這個對象的創(chuàng)建

package com.ymy.builder;import lombok.ToString; import org.springframework.util.StringUtils;@ToString public class ThreadConfig {/** * 核心線程默認值 */private static final Integer CORE_POOL_SIZE = 4;private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize = CORE_POOL_SIZE;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;public ThreadConfig(String threadName,Integer corePoolSize,Integer maxPoolSize,Integer queueCapacity,Integer keepAliveTime) throws IllegalAccessException {if(StringUtils.isEmpty(threadName)){throw new IllegalAccessException("線程名不能為空!");}this.threadName = threadName;if(null != corePoolSize ){if( corePoolSize <= 0){throw new IllegalAccessException("核心線程數(shù)不能小于等于0!");}this.corePoolSize = corePoolSize;}if(null != maxPoolSize ){if(maxPoolSize < this.corePoolSize){throw new IllegalAccessException("最大線程數(shù)不能小于核心線程數(shù)!");}this.maxPoolSize = corePoolSize;}if(null != queueCapacity ){if( queueCapacity <= 0 ){throw new IllegalAccessException("隊列書不能小于等于0!");}this.queueCapacity = queueCapacity;}if(null != keepAliveTime ){if( keepAliveTime <= 0 ){throw new IllegalAccessException("空閑時間不能小于等于0!");}this.keepAliveTime = keepAliveTime;}} }

@ToString注解是lombok依賴提供的

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

創(chuàng)建對象

package com.ymy.builder;public class Test {public static void main(String[] args) throws IllegalAccessException {ThreadConfig config = new ThreadConfig("thread-1",5,2,5,10);System.out.println(config);} }

輸出結(jié)果:

Exception in thread "main" java.lang.IllegalAccessException: 最大線程數(shù)不能小于核心線程數(shù)!at com.ymy.builder.ThreadConfig.<init>(ThreadConfig.java:56)at com.ymy.builder.Test.main(Test.java:6)

我這里給出的核心線程數(shù):5,但是最大線程數(shù)給的2,所以會拋出最大線程數(shù)不能小于核心線程數(shù)!這種方式看著很完美,但有一點很不友好,當參數(shù)過多的時候容易出錯,為什么這么說呢?你仔細看這行代碼

ThreadConfig config = new ThreadConfig("thread-1",5,2,5,10);

除了第一個參數(shù),其他參數(shù)都是int類型,看著好像沒啥大毛病,這是因為我的參數(shù)還不夠多,如果我這里有10個參數(shù)需要傳遞,并且都是int類型,這時候就會存在一個問題,參數(shù)很可能會被寫錯,比如最大線程數(shù)寫到了隊列數(shù)中,而且有時候還不會報錯,只有在項目運行的時候才會出現(xiàn)某種讓人摸不著頭腦的bug,所以使用構(gòu)造函數(shù)創(chuàng)建對象的時候不太適合參數(shù)過長,不但容易出錯,而且讓接手代碼的人也頭痛,代碼可讀性比較差,當然當參數(shù)只有一兩個的時候,構(gòu)造函數(shù)的創(chuàng)建方式還是很不錯的。

set方式構(gòu)建對象

既然構(gòu)造函數(shù)會導致參數(shù)錯誤以及可讀性較差,那我們能不能使用構(gòu)造函數(shù)+set方法來創(chuàng)建對象呢?我們可以嘗試一下,由于只有線程名是必傳,所以構(gòu)造函數(shù)只給定線程名,其他屬性都通過set賦值,改造一下代碼。

package com.ymy.builder;import lombok.ToString; import org.springframework.util.StringUtils;@ToString public class ThreadConfig {/** * 核心線程默認值 */private static final Integer CORE_POOL_SIZE = 4;private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize = CORE_POOL_SIZE;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;public ThreadConfig(String threadName) throws IllegalAccessException {if(StringUtils.isEmpty(threadName)){throw new IllegalAccessException("線程名不能為空!");}this.threadName = threadName;}public void setCorePoolSize(Integer corePoolSize) throws IllegalAccessException {if(null != corePoolSize ){if( corePoolSize <= 0){throw new IllegalAccessException("核心線程數(shù)不能小于等于0!");}this.corePoolSize = corePoolSize;}}public void setMaxPoolSize(Integer maxPoolSize) throws IllegalAccessException {if(null != maxPoolSize ){if(maxPoolSize < this.corePoolSize){throw new IllegalAccessException("最大線程數(shù)不能小于核心線程數(shù)!");}this.maxPoolSize = corePoolSize;}}public void setQueueCapacity(Integer queueCapacity) throws IllegalAccessException {if(null != queueCapacity ){if( queueCapacity <= 0 ){throw new IllegalAccessException("隊列書不能小于等于0!");}this.queueCapacity = queueCapacity;}}public void setKeepAliveTime(Integer keepAliveTime) throws IllegalAccessException {if(null != keepAliveTime ){if( keepAliveTime <= 0 ){throw new IllegalAccessException("空閑時間不能小于等于0!");}this.keepAliveTime = keepAliveTime;}}public void setAllowCoreThreadTimeout(boolean allowCoreThreadTimeout) {this.allowCoreThreadTimeout = allowCoreThreadTimeout;} }

改造完ThreadConfig之后我們創(chuàng)建對象的方式也會發(fā)生細微的變化,由之前構(gòu)造函數(shù)傳遞一堆參數(shù)變成了一個參數(shù),加上了set方法,初始值由set給定。

package com.ymy.builder;public class Test {public static void main(String[] args) throws IllegalAccessException {ThreadConfig config = new ThreadConfig("thread-1");config.setCorePoolSize(5);config.setMaxPoolSize(10);config.setQueueCapacity(2);config.setKeepAliveTime(100);config.setAllowCoreThreadTimeout(false);System.out.println(config);} }

這種對象的創(chuàng)建方式可以有效的防止賦值屬性錯亂的問題,因為看上去一目了然,基本上不會出錯,代碼可讀性也很強,完美的解決了將所有參數(shù)都放在構(gòu)造函數(shù)的缺陷,那為什么還會出現(xiàn)建造者模式呢?可以仔細想一下,set方法這么完美,建造者模式還有必要嗎?我覺得建造者模式的出現(xiàn)并不是偶然。

我們現(xiàn)在稍微修改一下需求:當corePoolSize(核心線程數(shù))被賦值的時候,最大線程數(shù)也必須要賦值,這個時候你覺得set方法還能滿足嗎?我覺得應該是滿足不了了吧,這是一種情況,還有一種情況set也是滿足不了的,那就是我希望對象初始化的時候一次性將所有的屬性都賦值,之后將不能被修改,這一點也是set做不到的,set方法就是提供給調(diào)用者的,所以調(diào)用者可以通過set隨時修改ThreadConfig的屬性,如果處理不當,可能會造成某種安全隱患,這個時候你可能又想到,把corePoolSize、maxPoolSize也放到構(gòu)造函數(shù)中不就解決了corePoolSize賦值的時候maxPoolSize也一定要賦值的要求嗎,確實是能解決這個問題,如果像這樣的參數(shù)很多呢?然后又有可能出現(xiàn)參數(shù)傳錯導致詭異bug,所這時候建造者模式就閃亮登場了。

java實現(xiàn)建造者模式

第一種實現(xiàn)方式

既然構(gòu)造函數(shù)和set方法無法滿足我們的需求,那自然會有滿足我們需求的新技術(shù)出現(xiàn),按照之前的需求,線程名必填、corePoolSize(核心線程數(shù))被賦值的時候,最大線程數(shù)也必須要賦值,我們一起使用建造模式來實現(xiàn)一下這個對象的創(chuàng)建。

package com.ymy.builder;import lombok.ToString; import org.springframework.util.StringUtils;@ToString public class ThreadConfig {/** * 核心線程默認值 */private static final Integer CORE_POOL_SIZE = 4;/** * 線程名 */private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize = CORE_POOL_SIZE;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;private ThreadConfig(ThreadConfig.Builder builder) {this.threadName = builder.threadName;if(null != builder.corePoolSize){this.corePoolSize = builder.corePoolSize;}this.maxPoolSize = builder.maxPoolSize;this.queueCapacity = builder.queueCapacity;this.keepAliveTime = builder.keepAliveTime;this.allowCoreThreadTimeout = builder.allowCoreThreadTimeout;}public static class Builder {/** * 線程名 */private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize ;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;public ThreadConfig build() throws IllegalAccessException { // 校驗邏輯放到這里來做,包括必填項校驗、依賴關(guān)系校驗、約束條件校驗等if (StringUtils.isEmpty(threadName)) {throw new IllegalAccessException("線程名不能為空");}if(corePoolSize != null && maxPoolSize == null){throw new IllegalAccessException("最大線程數(shù)必傳");}return new ThreadConfig(this);}public ThreadConfig.Builder corePoolSize(int corePoolSize) {if (corePoolSize <= 0) {throw new IllegalArgumentException("核心線程數(shù)不能小于等于0");}this.corePoolSize = corePoolSize;return this;}public ThreadConfig.Builder threadName(String threadName) {this.threadName = threadName;return this;}public ThreadConfig.Builder maxPoolSize(int maxPoolSize) {if (maxPoolSize < this.corePoolSize) {throw new IllegalArgumentException("最大線程數(shù)不能小于核心線程數(shù)");}this.maxPoolSize = maxPoolSize;return this;}public ThreadConfig.Builder queueCapacity(int queueCapacity) {if (queueCapacity <= 0) {throw new IllegalArgumentException("隊列不能小于等于0");}this.queueCapacity = queueCapacity;return this;}public ThreadConfig.Builder keepAliveTime(int keepAliveTime) {if (keepAliveTime <= 0) {throw new IllegalArgumentException("保持空閑線程可用的時間不能小于等于0");}this.keepAliveTime = keepAliveTime;return this;}public ThreadConfig.Builder allowCoreThreadTimeout(boolean allowCoreThreadTimeout) {this.allowCoreThreadTimeout = allowCoreThreadTimeout;return this;}}}

我們來測試,傳入核心線程數(shù)不傳最先線程數(shù)

package com.ymy.builder;public class Test {public static void main(String[] args) throws IllegalAccessException {ThreadConfig config = new ThreadConfig.Builder().threadName("hello").corePoolSize(3).keepAliveTime(100).queueCapacity(2).allowCoreThreadTimeout(true).build();System.out.println(config);} }

打印結(jié)果

Exception in thread "main" java.lang.IllegalAccessException: 最大線程數(shù)必傳at com.ymy.builder.ThreadConfig$Builder.build(ThreadConfig.java:89)at com.ymy.builder.Test.main(Test.java:12)

核心線程數(shù)不傳

ThreadConfig config = new ThreadConfig.Builder().threadName("hello")//.corePoolSize(3).keepAliveTime(100).queueCapacity(2).allowCoreThreadTimeout(true).build();System.out.println(config);

結(jié)果

ThreadConfig(threadName=hello, corePoolSize=4, maxPoolSize=null, queueCapacity=2, keepAliveTime=100, allowCoreThreadTimeout=true)Process finished with exit code 0

這就說明已經(jīng)達到了我們的預期效果,并且賦值清晰,不容易出錯,代碼的可讀性也比較高,但是也有一點是不足的,那就是ThreadConfig類中會出現(xiàn)冗余的數(shù)據(jù)Builder。

建造者模式的參數(shù)校驗放在了build()方法中,這樣做法的好處在于build是集中的處理參數(shù)問題,只有校驗通過之后才會給ThreadConfig對象實例化,為了對象的安全性,我們可以將ThreadConfig的構(gòu)造函數(shù)設(shè)置成private,同時取消set方法,強制使用builder方式創(chuàng)建對象,這樣就大大的保證了對象的安全性。

第二種方式

上面那種方式看著是不是很爽,但是創(chuàng)建對象的時候還是需要new ThreadConfig.Builder(),我現(xiàn)在想直接ThreadConfig.Builder()就能創(chuàng)建對象,我不想看到new,能不能實現(xiàn)呢?相信java,他能,我們一起來改造一下代碼

package com.ymy.builder;import lombok.ToString; import org.springframework.util.StringUtils;@ToString public class ThreadConfig {/** * 核心線程默認值 */private static final Integer CORE_POOL_SIZE = 4;/** * 線程名 */private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize = CORE_POOL_SIZE;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;private ThreadConfig(ThreadConfig.Builder builder) {this.threadName = builder.threadName;if(null != builder.corePoolSize){this.corePoolSize = builder.corePoolSize;}this.maxPoolSize = builder.maxPoolSize;this.queueCapacity = builder.queueCapacity;this.keepAliveTime = builder.keepAliveTime;this.allowCoreThreadTimeout = builder.allowCoreThreadTimeout;}/** * 使用靜態(tài)方法替代new * @return */public static Builder builder() {return new Builder();}public static class Builder {/** * 構(gòu)造函數(shù),可以不寫 */Builder(){}/** * 線程名 */private String threadName;/** * 核心線程數(shù) */private Integer corePoolSize ;/** * 最大線程數(shù) */private Integer maxPoolSize;/** * 隊列數(shù) */private Integer queueCapacity;/** * 當線程空閑時間達到keepAliveTime,該線程會退出 */private Integer keepAliveTime;/** * 是否允許核心線程數(shù)空閑時退出 */private boolean allowCoreThreadTimeout;public ThreadConfig build() throws IllegalAccessException { // 校驗邏輯放到這里來做,包括必填項校驗、依賴關(guān)系校驗、約束條件校驗等if (StringUtils.isEmpty(threadName)) {throw new IllegalAccessException("線程名不能為空");}if(corePoolSize != null && maxPoolSize == null){throw new IllegalAccessException("最大線程數(shù)必傳");}return new ThreadConfig(this);}public ThreadConfig.Builder corePoolSize(int corePoolSize) {if (corePoolSize <= 0) {throw new IllegalArgumentException("核心線程數(shù)不能小于等于0");}this.corePoolSize = corePoolSize;return this;}public ThreadConfig.Builder threadName(String threadName) {this.threadName = threadName;return this;}public ThreadConfig.Builder maxPoolSize(int maxPoolSize) {if (maxPoolSize < this.corePoolSize) {throw new IllegalArgumentException("最大線程數(shù)不能小于核心線程數(shù)");}this.maxPoolSize = maxPoolSize;return this;}public ThreadConfig.Builder queueCapacity(int queueCapacity) {if (queueCapacity <= 0) {throw new IllegalArgumentException("隊列不能小于等于0");}this.queueCapacity = queueCapacity;return this;}public ThreadConfig.Builder keepAliveTime(int keepAliveTime) {if (keepAliveTime <= 0) {throw new IllegalArgumentException("保持空閑線程可用的時間不能小于等于0");}this.keepAliveTime = keepAliveTime;return this;}public ThreadConfig.Builder allowCoreThreadTimeout(boolean allowCoreThreadTimeout) {this.allowCoreThreadTimeout = allowCoreThreadTimeout;return this;}} }

其實改動很小僅僅只是加了一個static Builder builder(),使用靜態(tài)方法替代new對象,這樣我們創(chuàng)建對象的時候就不需要new了,請看創(chuàng)建對象代碼

ThreadConfig config =ThreadConfig.builder().threadName("hello")// .corePoolSize(3).keepAliveTime(100).queueCapacity(2).allowCoreThreadTimeout(true).build();System.out.println(config);

是不是爽多了,看著真舒服,不過話說回來,你們看這種創(chuàng)建方式想不想lombok中給對象加了@Builder注解之后的創(chuàng)建方式?沒錯,就是一樣的,因為lombok中的@Builder就是建造者模式,只不過他的build并沒有我們這里的條件判斷,他是直接將屬性返回了。

建造者模式與構(gòu)造函數(shù)的對比

**構(gòu)造函數(shù):**適用于參數(shù)較少,邏輯簡單的對象創(chuàng)建,對于參數(shù)過多的對象創(chuàng)建可能會造成參數(shù)錯亂的問題而導致詭異bug。

**建造者模式:**適用于參數(shù)較多,邏輯判斷較復雜的對象創(chuàng)建,可以讓代碼簡潔明了,但是對象的代碼增加了,不但增加了很多冗余字段,所以有時候表面看起來光鮮亮麗,內(nèi)心卻是無比丑陋。

建造者模式與工廠模式的對比

對工廠模式還不太明白的朋友可以參考一下:工廠模式:你還在使用一堆的if/else創(chuàng)建對象嗎?
我們知道工廠模式主要是創(chuàng)建一個類型多個實現(xiàn)的對象,比如發(fā)送短信驗證碼的處理方式有很多種情況,每種情況的處理方式都不相同,還有就是創(chuàng)建對象的時候需要經(jīng)過很多的判斷,這種情況下我們就可以考慮使用工廠模式來創(chuàng)建對象。

如果對象的職責比較單一,沒有多層含義,僅僅只是創(chuàng)建條件復雜,參數(shù)過多等等,使用建造者模式創(chuàng)建對象是首選,雖然對象中含有冗余代碼,但是對象的創(chuàng)建真的很絲滑。

總結(jié)

如果一個類中包含著大量的屬性,我們可以通過構(gòu)造函數(shù)+set方法來進行對象創(chuàng)建,但對象如果包含一下幾點特性,那么我推薦使用建造者模式。
1.必填的字段很多,這樣會導致構(gòu)造函數(shù)參數(shù)過長的問題。
2.如果屬性與屬性之間關(guān)聯(lián)性很強,比如設(shè)置了核心線程數(shù)就必須要設(shè)置最大線程數(shù),這種情況下set方法是無法做到校驗的。
3.如果當前對象比較重要,我們希望對象被創(chuàng)建之后就不能被修改,所以這時候set方法就會被屏蔽,如果利用構(gòu)造函數(shù),又會出現(xiàn)字段過多問題。

當然了,我們不能為了用設(shè)計模式而用設(shè)計模式,對象一共就兩個屬性,我們也給他弄成建造者模式,這就有點大材小用,適得其反,一定要結(jié)合的實際的項目需求,不能盲目使用。

?

總結(jié)

以上是生活随笔為你收集整理的activexobject对象不能创建_【设计模式】建造者模式:你创建对象的方式有它丝滑吗?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。