01 設計模式入門

来源:https://www.cnblogs.com/ai1988/archive/2022/11/03/16854418.html
-Advertisement-
Play Games

熱度已經過了,但還是覺得有必要從架構設計的角度來討論一下此事。並用以往我的經驗來設計一套負載能力更好一些的系統。 先說一下基本的架構思路: 最大限度的避免計算,靜態化 不用資料庫,更新類操作使用APPEND模式的文本文件 流程最短,最好是客戶端訪問的第一臺伺服器就能完成全部工作 善用CDN 客戶端負 ...


一 什麼是設計模式

設計模式是一套反覆使用的代碼設計總結。使用設計模式是為了可重用代碼、保證代碼可靠性、程式的重用性。熟悉設計模式能更容易看懂框架源碼,更好的設計自己的系統。

二 設計模式分類

設計模式分為創建型、結構型和行為型三種模式。

三 設計模式的六大原則

開放封閉原則:儘量通過擴展軟體實體來解決需求變化,而不是通過修改已有的代碼來完成變化

里氏代換原則:使用的基類可以在任何地方使用繼承的子類,完美的替換基類。子類可以擴展父類的功能,但不能改變父類原有的功能。子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法【模版模式的鉤子方法不在此列】,子類中可以增加自己特有的方法

依賴倒轉原則:面向介面編程,我們在程式代碼中傳遞參數時或在關聯關係中,儘量引用層次高的抽象層類

介面隔離原則:使用多個隔離的介面,比使用單個介面要好

迪米特法則:一個類儘量減少自己對其他對象的依賴,簡稱類間解耦

單一職責原則:一個方法只負責一件事情

四 常用的設計模式

4.1 單例模式

使用場景:

網站計數器、應用程式日誌應用、線程池

註意事項:

註意線程安全問題

代碼實現:

  1 package com.leo.basic.code.design;
  2 
  3 /**
  4  * @DESCRIPTION
  5  * 單例模式:採用一定的方式保證一個類在一個系統中只有一個實例
  6  * 優點:單例模式保證了系統記憶體中該類只存在一個對象,節省了系統資源,對於一些需要頻繁創建銷毀的對象,使用單例模式可以提高系統性能
  7  * 缺點:由於單利模式中沒有抽象層,因此單例類的擴展有很大的困難;不適用於變化的對象
  8  * @DATE 2022-11-02
  9  * @AUTHOR liuzhilong
 10  */
 11 public class SingleTest {
 12 
 13     public static void main(String[] args) {
 14         // 1、餓漢式單例模式(靜態常量)
 15         Singleton1 singleton1 = Singleton1.getInstance();
 16         Singleton1 singleton2 = Singleton1.getInstance();
 17         System.out.println(singleton1 == singleton2);
 18         // 2、餓漢式單例模式(靜態代碼塊)
 19         Singleton2 singleton21 = Singleton2.getInstance();
 20         Singleton2 singleton22 = Singleton2.getInstance();
 21         System.out.println(singleton21 == singleton22);
 22         // 3、靜態內部類
 23         Singleton3 singleton31 = Singleton3.getInstance();
 24         Singleton3 singleton32 = Singleton3.getInstance();
 25         System.out.println(singleton31 == singleton32);
 26     }
 27 
 28 
 29 }
 30 // 實現方式
 31 // 1、餓漢式單例模式(靜態常量)
 32 class Singleton1 {
 33 
 34     private static Singleton1 instance = new Singleton1();
 35 
 36     private Singleton1() {
 37 
 38     }
 39 
 40     public static Singleton1 getInstance() {
 41         return instance;
 42     }
 43 }
 44 
 45 // 2、餓漢式單例模式(靜態代碼塊)
 46 class Singleton2 {
 47 
 48     private static Singleton2 instance;
 49 
 50     static {
 51         instance = new Singleton2();
 52     }
 53 
 54     private Singleton2() {
 55 
 56     }
 57 
 58     public static Singleton2 getInstance() {
 59         return instance;
 60     }
 61 }
 62 
 63 // 3、靜態內部類
 64 class Singleton3 {
 65 
 66     private Singleton3() {
 67 
 68     }
 69     // 採用了類裝載的機制來保證初始化實例時只有一個線程
 70     private static class Singleton3Instance{
 71         private static final Singleton3 instance = new Singleton3();
 72     }
 73 
 74     public static Singleton3 getInstance() {
 75         return Singleton3Instance.instance;
 76     }
 77 }
 78 
 79 // 4、枚舉
 80 enum Singleton4 {
 81     INSTANCE;
 82 }
 83 
 84 
 85 // 5、雙重檢查(Double-check)
 86 class Singleton5 {
 87 
 88     private static Singleton5 instance;
 89 
 90     private Singleton5() {
 91 
 92     }
 93     // 因為JVM本質重排序的原因,可能會初始化多次,不推薦使用
 94     public static Singleton5 getInstance() {
 95         if(instance == null){
 96             synchronized (Singleton5.class){
 97                 if(instance == null){
 98                     instance = new Singleton5();
 99                 }
100             }
101         }
102         return instance;
103     }
104 }
View Code

4.2 工廠模式

使用場景:

實例化對象、Spring IoC

註意事項:

代碼實現:

  1 package com.leo.basic.code.design;
  2 
  3 
  4 
  5 /**
  6  * @DESCRIPTION 工廠模式:
  7  * 簡單工廠:創建對象在工廠類中,工廠類很重【1類產品】
  8  * 工廠方法:創建對象在具體工廠實現類中,工廠是個介面【1類產品】
  9  * 抽象工廠:工廠中定義了一系列產品創建方法,創建對象在具體的工廠實現類中【多類產品】
 10  * 優點:在創建對象時不會對客戶端暴露創建邏輯,實現了創建者和調用者分離
 11  * 缺點:
 12  * @DATE 2022-11-02
 13  * @AUTHOR liuzhilong
 14  */
 15 public class FactoryTest {
 16 
 17     public static void main(String[] args) {
 18         // 1、簡單工廠
 19         Car aodi = SimpleCarFactory.createCar("奧迪");
 20         Car bmw = SimpleCarFactory.createCar("寶馬");
 21         aodi.run();
 22         bmw.run();
 23 
 24         // 2、工廠方法
 25         Car aodi1 = new AoDiFactory().createCar();
 26         Car jili1 = new BmwFactory().createCar();
 27         aodi1.run();
 28         jili1.run();
 29     }
 30 }
 31 
 32 // Car 產品
 33 interface Car {
 34 
 35     void run();
 36 }
 37 
 38 class Bmw implements Car {
 39 
 40     @Override
 41     public void run() {
 42         System.out.println("Bmw");
 43     }
 44 }
 45 
 46 class AoDi implements Car {
 47 
 48     @Override
 49     public void run() {
 50         System.out.println("AoDi");
 51     }
 52 }
 53 
 54 // 1、簡單工廠
 55 class SimpleCarFactory {
 56 
 57     public static Car createCar(String name) {
 58         if ("".equals(name)) {
 59             return null;
 60         }
 61         if (name.equals("奧迪")) {
 62             return new AoDi();
 63         }
 64         if (name.equals("寶馬")) {
 65             return new Bmw();
 66         }
 67         return null;
 68     }
 69 }
 70 
 71 
 72 // 2、工廠方法
 73 interface MethodCarFactory {
 74 
 75     Car createCar();
 76 }
 77 
 78 class AoDiFactory implements MethodCarFactory {
 79 
 80     public Car createCar() {
 81         return new AoDi();
 82     }
 83 }
 84 
 85 class BmwFactory implements MethodCarFactory {
 86 
 87     public Car createCar() {
 88         return new Bmw();
 89     }
 90 }
 91 
 92 // 3、抽象工廠
 93 // 發動機產品
 94 interface Engine {
 95     void run();
 96 }
 97 class EngineA implements Engine {
 98     public void run() {
 99         System.out.println("轉的快!");
100     }
101 }
102 class EngineB implements Engine {
103     public void run() {
104         System.out.println("轉的慢!");
105     }
106 }
107 
108 interface TotalFactory {
109     // 創建汽車
110     Car createChair();
111     // 創建發動機
112     Engine createEngine();
113 }
114 // 上海工廠實現類,由他決定調用哪個工廠的那個實例
115 class ShanghaiFactory implements TotalFactory {
116     public Engine createEngine() {
117         return new EngineA();
118     }
119     public Car createChair() {
120         return new AoDi();
121     }
122 }
View Code

4.3 模版模式

使用場景:

資料庫訪問的封裝、Junit單元測試、servlet中關於doGet/doPost方法的調用

註意事項:

代碼實現:

 1 package com.leo.basic.code.design;
 2 
 3 /**
 4  * @DESCRIPTION
 5  * 模版:定義一個操作中的演算法骨架(父類),而將一些步驟延遲到子類中,是一個流程!!。主要子類不能覆蓋父類的模版方法!!!
 6  * 優點:公共的邏輯代碼抽取,代碼復用;封裝不變的部分,重寫可變的部分,易擴展
 7  * 缺點:每來一個子類就要定義一套子類的規範,項目的體積會越來越大
 8  * @DATE 2022-11-02
 9  * @AUTHOR liuzhilong
10  */
11 public class TemplateTest {
12 
13     public static void main(String[] args) {
14         RestaurantTemplate restaurantTemplate = new RestaurantLobsterImpl();
15         restaurantTemplate.process();
16     }
17 }
18 
19 abstract class RestaurantTemplate {
20 
21     // 1.看菜單
22     public void menu() {
23         System.out.println("看菜單");
24     }
25 
26     // 2.點菜業務
27     abstract void spotMenu();
28 
29     // 3.吃飯業務
30     public void havingDinner() {
31         System.out.println("吃飯");
32     }
33 
34     // 4.付款業務
35     abstract void payment();
36 
37     // 5.走人
38     public void goR() {
39         System.out.println("走人");
40     }
41 
42     //模板通用結構
43     public void process() {
44         menu();
45         spotMenu();
46         havingDinner();
47         payment();
48         goR();
49     }
50 }
51 
52 class RestaurantLobsterImpl extends RestaurantTemplate {
53 
54     void spotMenu() {
55         System.out.println("龍蝦");
56     }
57 
58     void payment() {
59         System.out.println("50塊");
60     }
61 }
View Code

4.4 策略模式

使用場景:

策略模式的用意是針對一組演算法或邏輯,將每一個演算法或邏輯封裝到具有共同介面的獨立的類中,從而使得它們之間可以相互替換

註意事項:

代碼實現:

 1 package com.leo.basic.code.design;
 2 
 3 /**
 4  * @DESCRIPTION
 5  * 策略:定義了一系列的演算法 或 邏輯 或 相同意義的操作,並將每一個演算法、邏輯、操作封裝起來,而且使它們還可以相互替換。
 6  * 註意策略針對的是一個點,是一個演算法,不是流程。針對每個點實現一個具體的實現類,這點和模版方法不同!!!
 7  * 優點:1、演算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性非常良好
 8  * 缺點:1、策略類會增多。 2、所有策略類都需要對外暴露。
 9  * @DATE 2022-11-02
10  * @AUTHOR liuzhilong
11  */
12 public class StrategyTest {
13 
14     public static void main(String[] args) {
15         Context context;
16         //使用支付邏輯A
17         context = new Context(new PayStrategyA());
18         context.algorithmInterface();
19         //使用支付邏輯B
20         context = new Context(new PayStrategyB());
21         context.algorithmInterface();
22     }
23 }
24 
25 abstract class PayStrategy {
26 
27     // 支付邏輯方法
28     abstract void algorithmInterface();
29 }
30 
31 class PayStrategyA extends PayStrategy {
32 
33     void algorithmInterface() {
34         System.out.println("微信支付");
35     }
36 }
37 
38 class PayStrategyB extends PayStrategy {
39 
40     void algorithmInterface() {
41         System.out.println("支付寶支付");
42     }
43 }
44 
45 //定義下文維護演算法策略
46 class Context {
47 
48     PayStrategy strategy;
49 
50     public Context(PayStrategy strategy) {
51         this.strategy = strategy;
52     }
53 
54     public void algorithmInterface() {
55         strategy.algorithmInterface();
56     }
57 }
View Code

4.5 適配器模式

使用場景:

註意事項:

代碼實現:

 1 package com.leo.basic.code.design;
 2 
 3 /**
 4  * @DESCRIPTION
 5  * 適配器:將一個類的介面轉換成客戶希望的另外一個介面
 6  * 優點:讓原本因介面不匹配不能在一起工作的兩個類可以協同工作
 7  * 缺點:
 8  * @DATE 2022-11-03
 9  * @AUTHOR liuzhilong
10  */
11 public class AdapterTest {
12 
13     public static void main(String[] args) {
14         // 1、類適配器
15         //電腦,適配器,網線
16         Computer computer = new Computer();//電腦
17         Adapter adapter = new Adapter();//轉接器
18         computer.net(adapter);//電腦直接連接轉接器就可以
19 
20         // 2、對象適配器
21         Adapter2 adapter2 = new Adapter2(new Adaptee());//轉接器
22         computer.net(adapter2);
23 
24     }
25 }
26 
27 // 1、類適配器
28 //要適配的類:網線 -- Adaptee
29 class Adaptee {
30 
31     //功能:上網
32     public void request() {
33         System.out.println("鏈接網線上網");
34     }
35 }
36 
37 //介面轉換器的抽象實現 -- target
38 interface NetToUsb {
39     //作用:處理請求,網線=>usb
40     public void handleRequest();
41 }
42 
43 //真正的適配器,餘姚鏈接usb,連接網線 -- Adapter
44 class Adapter extends Adaptee implements NetToUsb{
45     @Override
46     public void handleRequest() {
47         super.request();//可以上網了
48     }
49 }
50 
51 //客戶端類:想上網,插不上網線
52 class Computer {
53     //電腦需要連接上轉接器才可以上網
54     public void net(NetToUsb adapter){
55         //上網的具體實現:找一個轉接頭
56         adapter.handleRequest();
57     }
58 }
59 
60 // 2、對象適配器
61 class Adapter2 implements NetToUsb {
62     private Adaptee adaptee;
63     public Adapter2(Adaptee adaptee){
64         this.adaptee = adaptee;
65     }
66     @Override
67     public void handleRequest() {
68         adaptee.request();;//可以上網了
69     }
70 }
View Code

4.6 建造者模式

使用場景:

需要生成的對象具有複雜的內部結構;需要生成的對象內部屬性本身相互依賴

註意事項:

代碼實現:

  1 package com.leo.basic.code.design;
  2 
  3 /**
  4  * @DESCRIPTION
  5  * 建造者:是將一個複雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的方式進行創建
  6  * 與工廠模式的區別是:建造者模式更加關註零件裝配的順序
  7  * 優點:
  8  * 缺點:
  9  * @DATE 2022-11-02
 10  * @AUTHOR liuzhilong
 11  */
 12 public class BuilderTest {
 13 
 14     public static void main(String[] args) {
 15         PersonDirector pb = new PersonDirector();

              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 邏輯導航 1.當在前端輸入用戶名和密碼之後,點擊登錄,後端校驗完畢返回前端 2.前端拿到需要首先做個判斷,判斷用戶是否輸入用戶名和密碼,未輸入則發出提示;輸入了則發送post請求給後端,校驗用戶名和密碼 3.校驗通過,前端拿到後端返回的token和用戶名等數據 4.登錄成功,則關閉登錄框,同時,在登 ...
  • 大部分同學都用過 CSS 的屏幕寬度媒體查詢,像是這樣: @media screen and (min-width: 900px) { div { padding: 1rem 3rem; } } 這裡表示的是與屏幕寬度相關的樣式設置,上面的代碼表示當屏幕寬度大於 900px 時,內部的樣式代碼塊才能 ...
  • 邏輯導航 1.當點擊頁面主頁的登錄/註冊按鈕時,彈出登錄/註冊模態框 2.登錄/註冊模態框也是一個小組件,在組件文件夾內創建對應組件 3.然後需要將該組件傳到header(頭部)組件內(進行相關的導入和註冊) 4. 補充子傳父組件語法 在子組件內 當點擊子組件里的東西時,傳遞給父組件一個事件,父組件 ...
  • 本文主要記錄 Vue.js 中的 Vuex,Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 ...
  • 當我們使用vuex的時候,時不時能看到“更改Vuex中的store中的狀態唯一辦法就是提交mutations”,但是有沒有試想過,我們不提交mutations其實也能修改state的值?答案是可以的 我們可以直接使用如下方式; this.$store.state.num=666; 其中,這樣修改的話 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 for in 和 for of 相對於大家肯定都不陌生,都是用來遍歷屬性的沒錯。那麼先看下麵的一個例子: 例1 const obj = { a: 1, b: 2, c: 3 } for (let i in obj) { console.l ...
  • 一、Yarn 產生的背景 Hadoop2 之前是由 HDFS 和 MR 組成的,HDFS 負責存儲,MR 負責計算。 一)MRv1 的問題 耦合度高:MR 中的 jobTracker 同時負責資源管理和作業控制兩個功能,互相制約。 可靠性差:管理節點是單機的,有單點故障的問題。 資源利用率低:基於 ...
  • 面向對象 一、三大特征之繼承 python三大特征: 封裝、繼承、多態 三者中繼承最為核心,實際應用多,感受較為直觀 封裝和多態略微抽象 1、繼承的概念 繼承的含義: ​ 在現實生活中,繼承表示人與人之間資源的從屬關係 ​ 例如:兒子繼承父親 ​ 在編程的世界中,繼承表示類與類之間的資源從屬關係 ​ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...