文章預覽:
- 一、工廠模式
- 1、介紹
- 2、實體
- (1)、典型的工廠模式
- (2)、多個工廠方法模式
- (3)、靜態工廠方法模式
- 3、總結
- 二、抽象工廠模式
- 1、介紹
- 2、實體
- 3、實體拓展
- 4、總結
- 三、建造者模式
- 1、介紹
- 2、實體
- 3、實體拓展
- 4、總結
- 四、原型模式
- 1、介紹
- 2、實體
- 3、實體拓展
- 4、總結
- 五、單例模式
- 1、介紹
- 2、實體
- (1)、懶漢式(執行緒不安全版)
- (2)、懶漢式(執行緒安全版)
- (3)、餓漢式(執行緒安全)
- (4)、使用類的內部類(執行緒安全)
- (5)、雙重鎖校驗(執行緒安全)
- (6)、CAS「AtomicReference」(執行緒安全)
- (7)、列舉單例(執行緒安全)
- 3、總結
一、工廠模式
1、介紹
? 這種設計模式也是 Java 開發中最常?的?種模式,又稱工廠方法模式,簡單說 在工廠類中提供?個創建物件的?法, 允許實際呼叫類決定實體化物件的型別,就是為了提供代碼結構的擴展性,屏蔽每?個功能類中的具體實作邏輯,讓外部可以更加簡單的只是知道調?即可,同時,這也是去掉眾多 ifelse 的?式,當然這可能也有?些缺點,?如需要實作的類?常多,如何去維護,怎樣減低開發成本,但這些問題都可以在后續的設計模式結合使?中,逐步降低,

2、實體
(1)、典型的工廠模式
以一個生產男鞋和女鞋的工廠為例:

工廠類和生產者介面:

男鞋和女鞋的實作類:

實際呼叫類:

輸出結果:
生產男鞋
生產女鞋
行程已結束,退出代碼為 0
(2)、多個工廠方法模式
與典型的工廠模式對比,Factory2將每個子類實體回傳封裝成單獨的方法

? 這也使得在實際呼叫中通過呼叫單獨不同的方法即可得到實體:這樣做的好處是不必關心觸發某個實體創建的邏輯,只需要呼叫創建某個實體的專有方法即可,

(3)、靜態工廠方法模式
將上面的多個工廠方法模式里的方法置為靜態的,使得工廠類不需要創建實體,直接呼叫即可,


3、總結
? 看完你看會覺得,只是判斷男鞋或女鞋從而覺得輸出陳述句業務,僅此而已,但是隨著業務邏輯的增加,不同業務型別決定各種各樣的邏輯功能時,事情也沒有那么簡單,比如若工廠實作的實體越來越多,而且實體間的相關性大大降低,這就凸顯了工廠模式的重要性,充分發揮出其避免創建者與具體的產品邏輯耦合 、 滿?單?職責,每?個業務邏輯實作都在所屬??的類中完成 、 滿?開閉原則,?需更改使?調??就可以在程式中引?新的產品型別的優點,
? 但這樣也會帶來?些問題,?如有?常多的獎品型別,那么實作的?類會極速擴張,因此也需要使?其他的模式進?優化,這些在后續的設計模式中會逐步涉及到,從案例??看設計模式往往要?看理論學的更加容易,因為案例是縮短理論到上?的最佳?式,如果你已經有所識訓,?定要去嘗試實操,

二、抽象工廠模式
1、介紹
? 抽象工廠模式其實就是在工廠模式的基礎上又添加了一層“工廠的工廠”,上述的工廠方法模式有一個問題就是,類的創建十分依賴工廠類,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則,所以,從設計角度考慮,有一定的問題,如何解決?就用到抽象工廠模式,創建多個工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼,

2、實體
? 仍然以男鞋女鞋工廠為例,與上面不同的是,該模式將“一個工廠生產兩種鞋”的業務變成了兩個工廠各自生產一種鞋,

兩個產品:

兩個工廠:

測驗:

3、實體拓展
以搭建Redis集群A、B為例:
可以預?的問題會有:
- 很多服務?到了Redis需要?起升級到集群,
- 需要兼容集群A和集群B,便于后續的災備,
- 兩套集群提供的接?和?法各有差異,需要做適配,
- 不能影響到?前正常運?的系統,
? 采?代理類的?式創建和獲取抽象工廠,所被代理的類就是Redis操作?法類,讓這個類在不需要任何修改下,就可以實作調?集群A和集群B的資料服務,
? 由于集群A和集群B在部分?法提供上是不同的,因此需要做?個接?適配(ICacheAdapter),?這個適配類就相當于??中的??,工廠A類和工廠B類實作了該適配介面,并且實作其方法,?于創建把不同的服務抽象為統?的接?做相同的業務,

4、總結
? 好處就是,如果你現在想增加一個功能:生產男鞋和女鞋以外的鞋,雖然這似乎不符合倫理道德,但實際業務可能就是需要實作,那么只需創建一個產品實作類,實作Product介面,同時創建一個工廠類,實作Producer介面就OK了,無需去改動現成的代碼,那么這個設計模式滿?了:單?職責、開閉原則、解耦等優點
? 但如果說隨著業務的不斷拓展,可能會造成類實作上的復雜度,但也可以說算不上缺點,因為可以隨著其他設計?式的引?和代理類以及?動?成加載的?式降低此項缺點,

三、建造者模式
1、介紹
? 建造者模式主要解決的問題是在軟體系統中,有時候?臨著"?個復雜物件"(鞋)的創建?作,其通常由各個部分的?物件??定的程序構成;由于需求的變化,這個復雜物件的各個部分經常?臨著重?的變化,但是將它們組合在?起(Builder)的程序卻相對穩定,
? 這?我們會把構建的程序交給 創建者 類,?創建者通過使?我們的 構建?具包 ,去構建出不同的生產方案,

2、實體

仍然是生產產品介面及其實作類:

建造者類發出命令分別生產3雙男鞋和2雙女鞋:

測驗結果:
生產男鞋
生產男鞋
生產男鞋
生產女鞋
生產女鞋
行程已結束,退出代碼為 0
3、實體拓展
? 現在我們在一個選擇裝修套餐(豪華歐式、輕奢?園、現代簡約三種)的場景下,利用建造者結合各種物料以及物料品牌做出構建方案,

? DecorationPackageMenu類通過實作IMenu介面,將不同的物料構建方法封裝進來,對外開放的引數只需要Builder將物料及品牌扔進去,讓DecorationPackageMenu處理后回傳IMenu即可,

4、總結
? 建造者模式將很多功能集成到一個類里,這個類可以創造出比較復雜的東西,所以與工廠模式的區別就是:工廠模式關注的是創建單個產品,而建造者模式則關注創建符合物件,多個部分,通過上?對建造者模式的使?,已經可以摸索出?點?得,那就是什么時候會選擇這樣的設計模式,當: ?些基本物料不會變,?其組合經常變化的時候 ,就可以選擇這樣的設計模式來構建代碼,此設計模式滿?了單?職責原則以及可復?的技術、建造者獨?、易擴展、便于控制細節?險,
? 但同時當出現特別多的物料以及很多的組合后,類的不斷擴展也會造成難以維護的問題,但這種設計結構模型可以把?復的內容抽象到資料庫中,按照需要配置,這樣就可以減少代碼中?量的重復,

四、原型模式
1、介紹
? 該模式的思想就是將一個物件作為原型,對其進行復制、克隆,產生一個和原物件類似的新物件,本小結會通過物件的復制,進行講解,
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yMTNgw7E-1635596243350)(C:\Users\CTC\Desktop\個人技術筆記\image-20211030175442342.png)]](https://img.uj5u.com/2021/10/31/2795823109492525.png)
2、實體
在Java中,復制物件是通過clone()實作的,先創建一個原型類:
public class Prototype implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
}
? 很簡單,一個原型類,只需要實作Cloneable介面,覆寫clone方法,此處clone方法可以改成任意的名稱,因為Cloneable介面是個空介面,你可以任意定義實作類的方法名,如cloneA或者cloneB,因為此處的重點是super.clone(),super.clone()呼叫的是Object的clone()方法,該方法本身其實是淺復制,首先了解物件深、淺復制的概念:
淺復制:將一個物件復制后,基本資料型別的變數都會重新創建,而參考型別,指向的還是原物件所指向的,
深復制:將一個物件復制后,不論是基本資料型別還有參考型別,都是重新創建的,簡單來說,就是深復制進行了完全徹底的復制,而淺復制不徹底,要實作深復制,需要采用流的形式讀入當前物件的二進制輸入,再寫出二進制資料對應的物件,
此處,寫一個深淺復制的例子:
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/* 淺復制 */
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深復制 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 寫入當前物件的二進制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 讀出二進制流產生的新物件 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
public SerializableObject getObj() {
return obj;
}
public void setObj(SerializableObject obj) {
this.obj = obj;
}
}
class SerializableObject implements Serializable {
private static final long serialVersionUID = 1L;
}
3、實體拓展
? 模擬出題方式,在這?模擬了兩個試卷題?的類; ChoiceQuestion (選擇題)、 AnswerQuestion (問答題),如果是實際的業務場景開發中,會有更多的題?型別,可以回憶?下你的?考試卷,
QuestionBank 克隆試卷物件處理類

QuestionBankController 初始化試卷資料類

? 這個類的內容就?較簡單了,主要提供對試卷內容的模式初始化操作(所有考?試卷?樣,題?順序不?致),以及對外部提供創建試卷的?法,在創建的程序中使?的是克隆的?式;(QuestionBank)questionBank.clone(),并最侄訓傳試卷資訊,
4、總結
? 以上的實際場景模擬了原型模式在開發中重構的作?,但是原型模式的使?頻率確實不是很?,如果有?些特殊場景需要使?到,也可以按照此設計模式進?優化,另外原型設計模式的優點包括:便于通過克隆?式創建復雜物件、也可以避免重復做初始化操作、不需要與類中所屬的其他類耦合等,但也有?些缺點如果物件中包括了回圈引?的克隆,以及類中深度使?物件的克隆,都會使此模式變得例外麻煩,

五、單例模式
1、介紹
? 單例模式可以說是整個設計中最簡單的模式之?,?且這種?式即使在沒有看設計模式相關資料也會常?在編碼開發中,因為在編程開發中經常會遇到這樣?種場景,那就是需要保證?個類只有?個實體哪怕多執行緒同時訪問,并需要提供?個全域訪問此實體的點,綜上以及我們平常的開發中,可以總結?條經驗,單例模式主要解決的是,?個全域使?的類頻繁的創建和消費,從?提升提升整體的代碼的性能,
技術場景:
- 資料庫的連接池不會反復創建
- spring中?個單例模式bean的?成和使?
- 在我們平常的代碼中需要設定全域的的?些屬性保存

2、實體
(1)、懶漢式(執行緒不安全版)
“你要的時候我才new,而且只new一次”
public class Singleton_01 {
private static Singleton_01 instance;
private Singleton_01() {}
public static Singleton_01 getInstance(){
if (null != instance){ //只能有一個實體
return instance;
}esle{
instance = new Singleton_01();
return instance;
}
}
}
? ?前此種?式的單例確實滿?了懶加載,但是如果有多個訪問者同時去獲取物件實體你可以想象成?堆?在搶廁所,就會造成多個同樣的實體并存,從?沒有達到單例的要求,
(2)、懶漢式(執行緒安全版)
public class Singleton_02 {
private static Singleton_02 instance;
private Singleton_02() {}
public static synchronized Singleton_01 getInstance(){ //設定同步鎖
if (null != instance){ //只能有一個實體
return instance;
}esle{
instance = new Singleton_01();
return instance;
}
}
}
此種模式雖然是執行緒安全的,但由于把鎖加到?法上后,所有的訪問都因需要鎖占?導致資源的浪費,如果不是特殊情況下,不建議此種?式實作單例模式,
(3)、餓漢式(執行緒安全)
"不管你要不要,我先new一個,而且只new一次"
public class Singleton_03 {
private static Singleton_03 instance = new Singleton_03();
private Singleton_03() {
}
public static Singleton_03 getInstance() {
return instance;
}
}
解釋:
由于instance為靜態實體,隨著類的加載而加載,呼叫靜態方法getInstance時,回傳的一直是這個一開始就被加載到記憶體里的instance實體,從而達到了單例的效果,
但此種?式并不是懶加載,也就是說?論你程式中是否?到這樣的類都會在程式啟動之初進?創建,那么這種?式導致的問題就像你下載個游戲軟體,可能你游戲地圖還沒有打開呢,但是程式已經將這些地圖全部實體化,到你?機上最明顯體驗就?開游戲記憶體滿了,?機卡了,需要換了,
(4)、使用類的內部類(執行緒安全)
此種?式是?常推薦使?的?種單例模式,
使?類的靜態內部類實作的單例模式,既保證了執行緒安全有保證了懶加載,即使用的時候只要呼叫getInstance方法,內部類SingletonHolder才會被加載從而實作了懶加載,同時不會因為加鎖的?式耗費性能,這主要是因為JVM虛擬機可以保證多執行緒并發訪問的正確性,也就是?個類的構造?法在多執行緒環境下可以被正確的加載,
public class Singleton_04 {
private Singleton_04() {}
private static class SingletonHolder {
private static Singleton_04 instance = new Singleton_04();
}
public static Singleton_04 getInstance() {
return SingletonHolder.instance;
}
}
(5)、雙重鎖校驗(執行緒安全)
public class Singleton_05 {
private static Singleton_05 instance;
private Singleton_05() {}
public static Singleton_05 getInstance(){
if(instance != null){
return instance;
}
synchronized (Singleton_05.class){ //保證執行緒安全
if (instance == null){
instance = new Singleton_05();
}
}
return instance;
}
}
? 雙重鎖的?式是?法級鎖的優化,其實就是懶漢式執行緒安全版的性能優化,因為懶漢式加了方法鎖,每次呼叫getInstance()時,都要對物件上鎖,實際上,只有第一次創建物件的時候才需要加鎖,所以可以改成如上的形式,減少了部分獲取實體的耗時,同時這種?式也滿?了懶加載,
(6)、CAS「AtomicReference」(執行緒安全)
public class Singleton_06 {
private static final AtomicReference<Singleton_06> ar =
new AtomicReference<Singleton_06>();
private static Singleton_06 instance;
private Singleton_06() {}
public static final Singleton_06 getInstance() {
for (; ; ) {
Singleton_06 instance = ar.get();
if (null != instance) return instance;
ar.compareAndSet(null, new Singleton_06());
return ar.get();
}
}
public static void main(String[] args) {
System.out.println(Singleton_06.getInstance());
//org.itstack.demo.design.Singleton_06@2b193f2d
System.out.println(Singleton_06.getInstance()); //org.itstack.demo.design.Singleton_06@2b193f2d
}
}
? java并發庫提供了很多原?類來?持并發訪問的資料安全性:AtomicInteger 、 AtomicBoolean 、 AtomicLong 、 AtomicReference ,
? AtomicReference 可以封裝引??個V實體,?持并發訪問如上的單例?式就是使?了這樣的?個特點,
? 使?CAS的好處就是不需要使?傳統的加鎖?式保證執行緒安全,?是依賴于CAS的忙等演算法,依賴于底層硬體的實作,來保證執行緒安全,相對于其他鎖的實作沒有執行緒的切換和阻塞也就沒有了額外的開銷,并且可以?持較?的并發性,當然CAS也有?個缺點就是忙等,如果?直沒有獲取到將會處于死回圈中,
(7)、列舉單例(執行緒安全)
public enum Singleton_07 {
INSTANCE;
public void test(){
System.out.println("hi~");
}
}
@Test
public void test() {
Singleton_07.INSTANCE.test();
}
? Effective Java 作者推薦使?列舉的?式解決單例模式,此種?式可能是平時最少?到的,這種?式解決了最主要的:執行緒安全、?由串?化、單?實體,?償地提供了串?化機制,絕對防?對此實體化,即使是在?對復雜的串?化或者反射攻擊的時候,雖然這種?法還沒有?泛采?,但是單元素的列舉型別已經成為實作Singleton的最佳?法,但也要知道此種?式在存在繼承場景下是不可?的,
3、總結
? 雖然只是?個很平常的單例模式,但在各種的實作上真的可以看到java的基本功的體現,這?包括了:懶漢、餓漢、執行緒是否安全、靜態類、內部類、加鎖、串?化等等,
? 在平時的開發中如果可以確保此類是全域可?不需要做懶加載,那么直接創建并給外部調?即可,但如果是很多的類,有些需要在?戶觸發?定的條件后才顯示,那么?定要?懶加載,執行緒的安全上可以按需選擇,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/342334.html
標籤:java
上一篇:Python:20行代碼爬取高質量帥哥美女視頻,讓你一次看個夠
下一篇:超詳細windows10下TensorFlow2.*安裝(對于intel處理器。tensorflow_cputensorflow_gpu)通用
