《設計模式七》備忘錄、模板方法、狀態模式及設計模式設計總結
1.19 備忘錄模式-Memento
記錄狀態,便於回滾
使用場景:例如磁碟快照,虛擬機器快照,遊戲存檔等
- Java中可以實現標記性介面,序列化需要存檔的類的狀態
public class A implements Serializable { int a = 1; int b = 2; B b = new B(); b.setHello("hello"); } public class B implements Serializable { public void setHello(String str) { System.out.println(str); } } // 存檔 public void save() throws Exception{ A a = new A(); File f = new File("d:test/a.data") ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f)); oss.writeObject(a); oss.close(); } // 讀盤 public void load() throws Exception{ A a = new A(); B b = new B(); File f = new File("d:test/a.data") ObjectInputStream oiss = new ObjectInputStream (new FileInputStream(f)); b = (B)ois.readObject(); a = (A)ois.readObject(); ois.close(); }
實質就是類的序列化和反序列化
序列化過程中transient修飾符,表示在序列化的過程中,transient修飾的類,進行透明處理,不進行序列化
總結:如果要序列化A,那麼A中其他物件的引用也要支援序列化,如果A中某個物件不需要序列化,可以使用transient使其透明化
序列化常被用來存檔,網路傳輸(不過目前基本不適用Java序列化進行網路傳輸,而是使用grpc,因為java的序列化傳輸會序列化很多屬性相關的用不到的東西,體量會比grpc大一到兩倍)
1.20 模板方法模式-TemplateMethod
通俗理解為鉤子函式
凡是我們重寫一個方法,系統幫我們重新呼叫的,都可以稱之為鉤子函式(模板方法)。
父類方法a呼叫的op1和op2兩個方法,子類重寫這兩個方法,呼叫父類的a方法,那麼被重寫的op1和op1們就會被父類呼叫
abstract class F { public void m() { op1(); op2(); } // 這兩個抽象方法就是留給子類去實現的 abstract void op1(); abstract void op2(); } class C1 extends F { @Override void op1() { System.out.println("op1"); } @Override void op2() { System.out.println("op2"); } } public class Main{ public static void main(String[] args) { F f = new C1(); f.m(); } }
1.21 狀態模式-State
根據狀態決定行為
例如,TCP連線中的客戶端Open呼叫,如果服務端是開啟的狀態採用何種open策略,如果服務端是監聽的採用何種open策略,如果服務端是關閉的,何種open策略。這裡服務端的這幾個條件就可以抽象成一個State。該State包涵上述的三個狀態,具體的連線要實現這三個狀態。所以State模式不適合頻繁擴充套件的方法,適合狀態固定的模式
1.21.1 有限狀態機(FSM)
- 例如:執行緒的遷移狀態
新建,就緒,執行,掛起...等等,有限的狀態機。State和有限狀態機實質是兩個東西,不可混淆
總結
- 看到某一個設計模式,要能想到這個模式的典型用法,聯想到使用場景。
重點設計模式
- 單例模式-singleton
- 工廠模式-Factory,包括靜態工程,動態工廠,Spring的Bean工廠
- 觀察者模式-Observer,監聽器,事件相關
- 介面卡模式-Adapter,IO的Stream流和Reader的轉換用來適配
- 代理模式-Proxy,靜態代理,動態代理,Spring的AOP
面向物件的六大原則
六大原則
- OCP : 總綱,對擴充套件開放,對修改關閉
- SRP : 類的職責要單一
- LSP : 子類可以透明替換父類
- DIR : 面向介面程式設計
- ISP : 介面的職責要單一
- LOD : 降低耦合
可維護性Maintainability
修改功能,需要改動的地方越少,可維護性越好
可複用性Reusability
程式碼可以被以後重複使用
寫出自己總結的類庫
可擴充套件性Extensibility/Scalability
新增功能無需修改原來程式碼
靈活性flexibility/mobility/adaptability
程式碼介面可以靈活呼叫
單一職責原則Single Responsiblity Principle
一個類別太大,被太累,負責單一的職責:Persion PersionManager
高內聚,低耦合
開閉原則 open-closed peinciple
對擴充套件開放,對修改關閉,儘量不修改原來的程式碼情況下進行擴充套件
抽象化,多型是開閉原則的關鍵
里氏替換原則Liscov Substitution Principle
所有使用父類的地方,必須能夠透明的使用子類物件,也就是說子類不要改父類的東西,不要更改父類的方法語義
例如F的子類是H:
F a = new F();
// 可以完全被替換為
F a = new H();
依賴倒置原則Dependency Inversion Priciple
- 依賴抽象,而不是依賴具體
- 面向抽象(介面)程式設計
介面隔離原則Interface Segregation Principle
每個介面應該承擔獨立的角色,不幹不該自己乾的事
- Flyable Runnable不該合二為一
- 避免子類實現不需要實現的方法
- 需要對客戶提供介面的時候,只需要暴露最小的介面