一、設計模式常用的七大原則有:
1) 單一職責原則 一個類只負責一項職責;提高類的可讀性,可維護性
2) 接口隔離原則 即一個類對另一個類的依賴 應該建立在最小的接口上
3) 依賴倒轉(倒置)原則 高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;依賴倒轉(倒置)的中心思想是面向接口編程
4) 里氏替換原則 在使用繼承時,遵循里氏替換原則,在子類中儘量不要重寫父類的方法;在適當的情況下,可 以通過聚合,組合,依賴 來解決問題。.
5) 開閉原則 類,模塊和函數應該對擴展開放(對提供方),對修改關閉(對使用 方)。用抽象構建框架,用實現擴展細節;當軟件需要變化時,儘量通過擴展軟件實體的行爲來實現變化,而不是通過修改已 有的代碼來實現變化。
6) 迪米特法則 (最少知道原則) 迪米特法則的核心是降低類之間的耦合
7) 合成複用原則 原則是儘量使用合成/聚合的方式,而不是使用繼承
總結:
1) 找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代 碼混在一起。
2) 針對接口編程,而不是針對實現編程。
3) 爲了交互對象之間的松耦合設計而努力
二、設計模式分爲三種類型,共23種
1) 創建型模式:單例模式、抽象工廠模式、原型模式、建造者模式、工廠模式。
2) 結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享 元模式、代理模式。
3) 行爲型模式:模版方法模式、命令模式、訪問者模式、迭代器模式、觀察者 模式、中介者模式、備忘錄模式、解釋器模式(Interpreter模式)、狀態模 式、策略模式、職責鏈模式(責任鏈模式)。
三、單例模式:
①、什麼是單例:
所謂類的單例設計模式,就是採取一定的方法保證在整個的軟件系統中,對某個類 只能存在一個對象實例,並且該類只提供一個取得其對象實例的方法(靜態方法)。
②、單例模式有八種方式:
1) 餓漢式(靜態常量)
2) 餓漢式(靜態代碼塊)
3) 懶漢式(線程不安全)
4) 懶漢式(線程安全,同步方法)
5) 懶漢式(線程安全,同步代碼塊)
6) 雙重檢查
7) 靜態內部類
8) 枚舉
1、餓漢式(靜態常量)應用實例 步驟如下:
1) 構造器私有化 (防止 new )
2) 類的內部創建對象
3) 向外暴露一個靜態的公共方法。getInstance
4) 代碼實現
class Singleton {
//1. 構造器私有化, 外部能new
private Singleton() {
}
//2.本類內部創建對象實例
private final static Singleton instance = new Singleton();
//3. 提供一個公有的靜態方法,返回實例對象
public static Singleton getInstance() {
return instance;
}
}
1) 優點:這種寫法比較簡單,就是在類裝載的時候就完成實例化。避免了線程同 步問題。
2) 缺點:在類裝載的時候就完成實例化,沒有達到Lazy Loading的效果。如果從始 至終從未使用過這個實例,則會造成內存的浪費
2、餓漢式(靜態代碼塊)應用實例
/餓漢式(靜態變量)
class Singleton {
//1. 構造器私有化, 外部能new
private Singleton() {
}
//2.本類內部創建對象實例
private static Singleton instance;
static { // 在靜態代碼塊中,創建單例對象
instance = new Singleton();
}
//3. 提供一個公有的靜態方法,返回實例對象
public static Singleton getInstance() {
return instance;
}
}
優缺點同上可用
3、懶漢式(線程不安全)
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一個靜態的公有方法,當使用到該方法時,纔去創建 instance
//即懶漢式
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
優缺點說明:
1) 起到了Lazy Loading的效果,但是隻能在單線程下使用。
2) 如果在多線程下,一個線程進入了if (singleton == null)判斷語句塊,還未來得及 往下執行,另一個線程也通過了這個判斷語句,這時便會產生多個實例。所以 在多線程環境下不可使用這種方式
3) 結論:在實際開發中,不要使用這種方式.
4、懶漢式(線程安全,同步方法)
// 懶漢式(線程安全,同步方法)
class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一個靜態的公有方法,加入同步處理的代碼,解決線程安全問題
//即懶漢式
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
優缺點說明:
1) 解決了線程不安全問題
2) 效率太低了,每個線程在想獲得類的實例時候,執行getInstance()方法都要進行 同步。而其實這個方法只執行一次實例化代碼就夠了,後面的想獲得該類實例, 直接return就行了。方法進行同步效率太低
3) 結論:在實際開發中,不推薦使用這種方式
5、懶漢式(線程安全,同步代碼塊)
6、雙重檢查應用實例
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
//提供一個靜態的公有方法,加入雙重檢查代碼,解決線程安全問題, 同時解決懶加載問題
//同時保證了效率, 推薦使用
public static synchronized Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
1) 線程安全;延遲加載;效率較高
2) 結論:在實際開發中,推薦使用這種單例設計模式
7、靜態內部類應用實例
// 靜態內部類完成, 推薦使用
class Singleton {
private static volatile Singleton instance;
//構造器私有化
private Singleton() {}
//寫一個靜態內部類,該類中有一個靜態屬性 Singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一個靜態的公有方法,直接返回SingletonInstance.INSTANCE
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
優缺點說明:
1) 這種方式採用了類裝載的機制來保證初始化實例時只有一個線程。
2) 靜態內部類方式在Singleton類被裝載時並不會立即實例化,而是在需要實例化 時,調用getInstance方法,纔會裝載SingletonInstance類,從而完成Singleton的 實例化。
3) 類的靜態屬性只會在第一次加載類的時候初始化,所以在這裏,JVM幫助我們 保證了線程的安全性,在類進行初始化時,別的線程是無法進入的。
4) 優點:避免了線程不安全,利用靜態內部類特點實現延遲加載,效率高
5) 結論:推薦使用.
8、枚舉應用實例
//使用枚舉,可以實現單例, 推薦
enum Singleton {
INSTANCE; //屬性
public void sayOK() {
System.out.println("ok~");
}
}
public class SingletonTest08 {
public static void main(String[] args) {
Singleton instance = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance == instance2);
System.out.println(instance.hashCode());
System.out.println(instance2.hashCode());
instance.sayOK();
}
}
優缺點說明:
1) 這藉助JDK1.5中添加的枚舉來實現單例模式。不僅能避免多線程同步問題,而 且還能防止反序列化重新創建新的對象。
2) 這種方式是Effective Java作者Josh Bloch 提倡的方式
3) 結論:推薦使用