目錄 · 總述 · 記憶 · 效果 · 面向對象設計原則 · 創建型模式 · 單例模式(Singleton) · 效果 · 分類 · 代碼(餓漢式) · 代碼(懶漢式) · 代碼(雙重檢測鎖式) · 代碼(靜態內部類式) · 代碼(枚舉單例) · 代碼(使用反射的破解與防禦) · 代碼(使用序列化的 ...
目錄
· 總述
· 記憶
· 效果
· 面向對象設計原則
· 創建型模式
· 效果
· 分類
· 代碼(餓漢式)
· 代碼(懶漢式)
· 代碼(枚舉單例)
· 應用場景
· 工廠模式
· 效果
· 分類
· 代碼(簡單工廠)
· 代碼(工廠方法)
· 代碼(抽象工廠)
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼(淺克隆)
· 應用場景
· 結構型模式
· 效果
· 核心角色
· 分類
· 代碼(使用繼承)
· 代碼(使用關聯)
· 應用場景
· 效果
· 核心角色
· 分類
· 代碼(靜態代理)
· 代碼(動態代理)
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 代碼(殺毒舉例)
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
· 行為型模式
· 責任鏈模式(Chain of Resposibility)
· 效果
· 核心角色
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
· 效果
· 應用場景
· 效果
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
· 效果
· 代碼
· 應用場景
· 效果
· 核心角色
· 代碼
· 應用場景
總述
記憶
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();