設計模式筆記——GoF設計模式彙總

来源:http://www.cnblogs.com/netoxi/archive/2017/08/07/7259863.html
-Advertisement-
Play Games

目錄 · 總述 · 記憶 · 效果 · 面向對象設計原則 · 創建型模式 · 單例模式(Singleton) · 效果 · 分類 · 代碼(餓漢式) · 代碼(懶漢式) · 代碼(雙重檢測鎖式) · 代碼(靜態內部類式) · 代碼(枚舉單例) · 代碼(使用反射的破解與防禦) · 代碼(使用序列化的 ...


目錄

· 總述

    · 記憶

    · 效果

    · 面向對象設計原則

· 創建型模式

    · 單例模式(Singleton)

        · 效果

        · 分類

        · 代碼(餓漢式)

        · 代碼(懶漢式)

        · 代碼(雙重檢測鎖式)

        · 代碼(靜態內部類式)

        · 代碼(枚舉單例)

        · 代碼(使用反射的破解與防禦)

        · 代碼(使用序列化的破解與防禦)

        · 應用場景

    · 工廠模式

        · 效果

        · 分類

        · 代碼(簡單工廠)

        · 代碼(工廠方法)

        · 代碼(抽象工廠)

        · 應用場景

    · 構建者模式(Builder)

        · 效果

        · 代碼

        · 應用場景

    · 原型模式(Prototype)

        · 效果

        · 核心角色

        · 代碼(淺克隆)

        · 代碼(基於JDK的深克隆)

        · 代碼(基於序列化的深克隆)

        · 應用場景

· 結構型模式

    · 適配器模式(Adapter)

        · 效果

        · 核心角色

        · 分類

        · 代碼(使用繼承)

        · 代碼(使用關聯)

        · 應用場景

    · 代理模式(Proxy)

        · 效果

        · 核心角色

        · 分類

        · 代碼(靜態代理)

        · 代碼(動態代理)

        · 應用場景

    · 橋接模式(Bridge)

        · 效果

        · 代碼

        · 應用場景

    · 組合模式(Composite)

        · 效果

        · 核心角色

        · 代碼

        · 代碼(殺毒舉例)

        · 應用場景

    · 裝飾器模式(Decorator)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

    · 外觀模式(Facade)

        · 效果

        · 代碼

        · 應用場景

    · 享元模式(FlyWeight)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

· 行為型模式

    · 責任鏈模式(Chain of Resposibility)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

    · 迭代器模式(Iterator)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

    · 中介者模式(Mediator)

        · 效果

        · 代碼

        · 應用場景

    · 命令模式(Command)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

    · 解釋器模式(Interpreter)

        · 效果

        · 應用場景

    · 訪問者模式(Visitor)

        · 效果

        · 應用場景

    · 策略模式(Strategy)

        · 效果

        · 代碼

        · 應用場景

    · 模板方法模式(Template Method)

        · 效果

        · 代碼

        · 應用場景

    · 狀態模式(State)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景

    · 觀察者模式(Observer)

        · 效果

        · 代碼

        · 代碼(基於JDK)

        · 應用場景

    · 備忘錄模式(Memento)

        · 效果

        · 核心角色

        · 代碼

        · 應用場景


 

總述

記憶

1. 創建型:bpfs;

2. 結構型:abcdffp;

3. 行為型:iimmccsstov。

效果

1. 所有面向對象設計原則和設計模式都是為了降低代碼耦合度,提高擴展性、復用,手段是“分工”。

2. 類似社會分工,現代社會比原始社會發展得大,也是因為分工。

面向對象設計原則

1. OCP(開閉原則,Open Closed Principle):一個軟體的實體應當對擴展開放,對修改關閉。

2. DIP(依賴倒轉原則,Dependence Inversion Principle):要針對介面編程,不要針對實現編程。

3. LoD(迪米特法則,Law of Demeter):只與你直接的朋友通信,而避免和陌生人通信。

創建型模式

單例模式(Singleton)

效果

1. 保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問點。

2. 由於單例模式只生成一個實例,減少了系統性能開銷,當一個對象的產生需要比較多的資源時,如讀取配置、產生其他依賴對象時,則可以通過在應用啟動時直接產生一個單例對象,然後永久駐留記憶體的方式來解決。

分類

1. 常見實現方式。

    a) 餓漢式:線程安全,調用效率高,不能延時載入。

    b) 懶漢式:線程安全,調用效率不高,可延時載入。

2. 其他實現方式。

    a) 雙重檢測鎖式:由於JVM底層內部模型原因,偶爾出問題,不建議使用。

    b) 靜態內部類式:線程安全,調用效率高,可延時載入。

    c) 枚舉單例:線程安全,調用效率高,不能延時載入。

3. 選擇方法。

    a) 單例對象占用資源少,不需要延時載入:枚舉式好於餓漢式;

    b) 單例對象占用資源多,需要延時載入:靜態內部類好於懶漢式。

代碼(餓漢式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     // 類初始化時立即創建對象
 4     private static final Singleton instance = new Singleton();
 5     
 6     // 私有化構造器
 7     private Singleton() {
 8         if (instance != null) {
 9             throw new RuntimeException();
10         }
11     }
12     
13     public static Singleton getInstance() {
14         return instance;
15     }
16     
17 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代碼(懶漢式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     private static Singleton instance;
 4     
 5     // 私有化構造器
 6     private Singleton() {
 7     }
 8     
 9     // 同步方法
10     public static synchronized Singleton getInstance() {
11         if (instance == null) {
12             // 延時載入
13             instance = new Singleton();
14         }
15         return instance;
16     }
17     
18 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代碼(雙重檢測鎖式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     private static volatile Singleton instance;
 4     
 5     // 私有化構造器
 6     private Singleton() {
 7     }
 8     
 9     public static Singleton getInstance() {
10         if (instance == null) {
11             // 第一次創建時同步
12             synchronized (Singleton.class) {
13                 if (instance == null) {
14                     // 延時載入
15                     instance = new Singleton();
16                 }
17             }
18         }
19         return instance;
20     }
21     
22 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代碼(靜態內部類式)

1. Singleton.java

 1 public class Singleton {
 2     
 3     // 初始化外部類時不會立即初始化內部類
 4     private static class SingletonInstance {
 5         private static final Singleton instance = new Singleton();
 6     }
 7 
 8     // 私有化構造器
 9     private Singleton() {
10     }
11     
12     public static Singleton getInstance() {
13         return SingletonInstance.instance;
14     }
15     
16 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代碼(枚舉單例)

1. Singleton.java

 1 public enum Singleton {
 2     
 3     // 枚舉本身就是單例
 4     INSTANCE;
 5     
 6     // 添加需要的方法
 7     public void method() {
 8     }
 9     
10 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.INSTANCE;
5         Singleton singleton2 = Singleton.INSTANCE;
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代碼(使用反射的破解與防禦)

1. Singleton.java

 1 public class Singleton {
 2 
 3     // 類初始化時立即創建對象
 4     private static final Singleton instance = new Singleton();
 5     
 6     // 私有化構造器
 7     private Singleton() {
 8         // 防禦:再次創建時拋出異常
 9         if (instance != null) {
10             throw new RuntimeException();
11         }
12     }
13     
14     public static Singleton getInstance() {
15         return instance;
16     }
17     
18 }
View Code

2. Client.java

 1 import java.lang.reflect.Constructor;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) throws Exception {
 6         Singleton singleton1 = Singleton.getInstance();
 7         
 8         Class<Singleton> clazz = Singleton.class;
 9         Constructor<Singleton> constructor = clazz.getDeclaredConstructor();
10         constructor.setAccessible(true);
11         Singleton singleton2 = constructor.newInstance();
12         System.out.println(singleton1 == singleton2);
13     }
14 
15 }
View Code

代碼(使用序列化的破解與防禦)

1. Singleton.java

 1 import java.io.Serializable;
 2 
 3 public class Singleton implements Serializable {
 4 
 5     private static final long serialVersionUID = -3230831923851678463L;
 6     
 7     // 類初始化時立即創建對象
 8     private static final Singleton instance = new Singleton();
 9     
10     // 私有化構造器
11     private Singleton() {
12     }
13     
14     public static Singleton getInstance() {
15         return instance;
16     }
17     
18     // 防禦:反序列化時,直接返回該方法的返回值
19     private Object readResolve() {
20         return instance;
21     }
22     
23 }
View Code

2. Client.java

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 
 7 public class Client {
 8 
 9     public static void main(String[] args) throws Exception {
10         Singleton singleton1 = Singleton.getInstance();
11         
12         File tempFile = new File("D:/test");
13         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tempFile));
14         oos.writeObject(singleton1);
15         oos.close();
16         ObjectInputStream ios = new ObjectInputStream(new FileInputStream(tempFile));
17         Singleton singleton2 = (Singleton) ios.readObject();
18         ios.close();
19         System.out.println(singleton1 == singleton2);
20         
21     }
22 
23 }
View Code

應用場景

1. Windows的Task Manager(任務管理器)。

2. Windows的Recycle Bin(回收站)。

3. 項目中,讀取配置文件的類,一般只有一個對象,沒必要每次創建。

4. 資料庫連接池。

5. Application是單例的典型應用(Servlet編程)。

6. Spring中,每個Bean預設是單例的。

7. 每個Servlet是單例。

8. Spring MVC中,控制器對象是單例的。

工廠模式

效果

1. 實例化對象,用工廠方法代替new。實現了創建者和調用者的分離。

2. 將選擇實現類、創建對象統一管理和控制,從而將調用者跟我們的實現類解耦。

分類

1. 簡單工廠模式:用來產生同一等級結構中的任意產品。對於增加新的產品,需要修改已有代碼。

2. 工廠方法模式:用來產生同一等級結構中的固定產品。支持增加任意產品。

3. 抽象工廠模式:用來生產不同產品族的全部產品。對於增加新的產品,無能為力;支持增加產品族。

4. 簡單工廠模式效果:

    a) 又稱靜態工廠模式。

    b) 工廠類一般使用靜態方法,通過接收的參數來返回不同的對象實例。

    c) 對於增加新產品只能修改代碼(違反OCP)。

    d) 有兩種實現方式(見代碼)。

5. 工廠方法模式效果:

    a) 避免簡單工廠的缺點,但不完全滿足OCP。

    b) 簡單工廠模式VS.工廠方法模式:

        i. 結構複雜度:顯然簡單工廠模式占優,簡單工廠模式只要一個工廠,而工廠方法模式的工廠類隨著產品類個數增加而增加。

        ii. 代碼複雜度:代碼複雜度與結構複雜度相反,簡單工廠模式的工廠類隨著產品增加需要增加更多方法(代碼),而工廠方法模式每個具體工廠類只完成單一任務,代碼簡單。

        iii. 客戶端編程難度:工廠方法模式雖然滿足了OCP,但客戶端編碼中需要對工廠實例化,而簡單工廠模式的工廠類是一個靜態類。

        iv. 管理上的難度:工廠方法模式需要維護的工廠類過多,而簡單工廠模式只有一個。

    c) 設計理論建議使用工廠方法模式,但實際中一般都用簡單工廠模式。

6. 抽象工廠模式效果:

    a) 用來生產不同產品族的全部產品。對於增加新的產品,無能為力;支持增加產品族。

    b) 抽象工廠模式是工廠方法模式的升級版本,在有多個業務品種、業務分類時,通過抽象工廠模式產生需要的對象時一種非常好的解決方式。

代碼(簡單工廠)

1. Car.java

1 public interface Car {
2 
3     void run();
4     
5 }
View Code

2. Audi.java

1 public class Audi implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("奧迪在跑!");
6     }
7 
8 }
View Code

3. Byd.java

1 public class Byd implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("比亞迪在跑!");
6     }
7 
8 }
View Code

4. CarFactory.java

 1 // 一個方法實現
 2 public class CarFactory1 {
 3 
 4     public static Car createCar(String type) {
 5         if ("Audi".equals(type)) {
 6             return new Audi();
 7         }
 8         if ("Byd".equals(type)) {
 9             return new Byd();
10         }
11         return null;
12     }
13     
14 }
View Code

5. CarFactory2.java

 1 // 多個方法實現
 2 public class CarFactory2 {
 3     
 4     public static Car createAudi() {
 5         return new Audi();
 

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

-Advertisement-
Play Games
更多相關文章
  • 寫在前面: 最近在項目中,遇到一個問題,在點擊一個超鏈接時,頁面報錯。通過瀏覽器調試就可以知道發送的請求參數是不完整的,因為參數中含有特殊字元。所以就報錯啦~~ 原代碼,不能正確發送含有特殊字元的參數: 其中k_projectname中是含有特殊字元的,比如#,在發送請求的時候就不能被識別,需要對其 ...
  • 閱讀目錄: 事件綁定 Toplevel組件 標準對話框 事件綁定 事件綁定: 說明:對於每個組件來說,可以通過bind()方法將函數或方法綁定到具體的事件上。 事件序列: 說明:用戶需要使用bind()方法將具體的事件序列與自定義的方法綁定,時間序列是以字元串的形式表示的。 語法描述: <modif ...
  • 今天我分享一個技術點,利用Spring初始化+線程接管進行程式啟動後保持會話狀態。 先來一段@test單元測試註解,後臺開發的很熟悉,這是測試局部代碼用的: RunWith和ContextConfiguration的源碼和功能就不細解釋了,不熟悉的可以去翻翻源碼。 1:我來一段@Test單元測試操作 ...
  • 工具:eclipse-nion、jdk8、python3.6、pydev eclipse -》 help -》 eclipse marketplace -》 輸入 python,install pydev 接著配置一下eclipse的解釋器以及編碼方式 新建一個項目:new -》project -》 ...
  • /** * 剪切一個文件夾,且文件夾中包含內容,有問題的地方大家可以指出 */import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileI ...
  • 本節作業: 熟練使用類和模塊,寫一個交互性強、有衝突的程式。 一、作業目的 1、規範程式寫法,要按照模塊來規範書寫; 2、類的使用,文件之間的調用練習; 3、思路的開闊,自己編寫衝突,實現調用; 4、對基礎知識的熟練掌握。 本文寫了一個決鬥系統,兩個男的為了一個女的進行決鬥,獲勝者贏得美女放心,失敗 ...
  • 本文介紹將各種Spring的配置方式,幫助您瞭解配置Spring應用的複雜性。Spring是一個非常受歡迎的Java框架,它用於構建web和企業應用。不像許多其他框架只關註一個領域,Spring框架提供了各種功能,通過項目組合來滿足當代業務需求。Spring框架提供了多種靈活的方式配置Bean。例如... ...
  • mybatis 詳解(四)------properties以及別名定義 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...