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不該合二為一
- 避免子類實現不需要實現的方法
- 需要對客戶提供介面的時候,只需要暴露最小的介面