設計模式學習總結(Java版)
設計模式只是一種指導思想
共23種設計模式 ,儘量精簡,方便複習,程式語言是Java
單例模式
概述:確保一個類只有一個例項,而且自行例項化並向整個系統提供這個唯一的例項。
要點:構造方法是private
、有當前類的靜態成員變數,用static
修飾、例項只能在內部例項化
作用:確保一個類只有一個例項存在,方便控制物件,節省資源
舉例:序列號生成器,Web頁面的計數器,建立消耗大的物件,spring IOC容器,Runtime類,Proxy類
實現:餓漢式、懶漢式、列舉類。。。。。 注意併發/多執行緒的情況
簡單工廠模式
概述:又稱靜態方法工廠模式,它屬於類建立型模式。可根據引數的不同返回不同類的例項。就專門定義一個類來負責建立其他類例項的。被建立的例項通常都具有共同的父類。
要點:它知道每個產品,它決定哪個產品應當被例項化,而無需知道建立細節。一般使用靜態方法(就不能在子類中對其進行擴充套件)。
作用:解耦 解耦 解耦,將例項化物件的程式碼提取出來,放到一個類中管理維護。
舉例:DateFormat類,Calendar類,Logger類,JDBC中Connection物件的獲取;
實現:
public class SimpleCarFactory { public static Car getCar(String type) { if (type.equalsIgnoreCase("BMW")) { // .... return new BMWCard(); } else if (type.equalsIgnoreCase("Audi")) { // .... return new AudiCard(); } else throw new IllegalArgumentException("No such brand!"); } }
工廠模式
概述:定義一個用於建立物件的介面(抽象),讓子類(具體)決定例項化哪個類,工廠方法使一個類的例項化延遲到子類。在工廠模式中新增一個產品,不改原有的工廠類,而是新增一個工廠(別問,問就是開閉原則,擴充套件優於修改。符合單一職責原則,每個具體工廠類只負責建立對應的產品)
要點:工廠類是抽象的,它定義工廠應該有哪些方法,然後有很多實現類 比如工廠A,工廠B。一個工廠只能建立一種具體產品
舉例:Collection介面中Iterator的生成,具體工廠如LinkedList,ArrayList 抽象產品如Iterator,具體產品就是ListItr,Itr
實現:
interface AbstractCarFactory { Car createCar(); } class BWMCarFactory implements AbstractCarFactory{ @Override public Car createCar() { return new BWMCar(); } } class AudiCarFactory implements AbstractCarFactory{ @Override public Car createCar() { return new AudiCar(); } }
擴充套件:設計模式的依賴抽象原則
- 建立物件例項時,不要直接
new
類, 而是把這個new
類的動作放在一個工廠的方法中,並返回。有的書上說,變數不要直接持有具體類的引用。 - 不要讓類繼承具體類,而是繼承抽象類或者是實現interface(介面)
- 不要覆蓋基類中已經實現的方法。
抽象工廠模式
概述:工廠模式下只能建立一大類的產品, 抽象工廠使得工廠不單單生成那具體的某一大類,還可以生產其他大類產品。它打破工廠與具體產品的一對一關係。是工廠模式的一種擴充套件。 它能建立一系列相關或相互依賴的物件, 而無需指定其具體類。
要點:新增新產品要修改抽象工廠和具體工廠的程式碼,也不是宣告為abstract
的簡單工廠
舉例:Spring的BeanFactory類,Java.sql包,Collection介面,涉及到產品系列
裝飾器模式
概述:動態地給一個物件新增一些額外的功能。就增加功能來說,裝飾模式比生成子類更加靈活。是繼承關係的一個替代方案。在不影響其他物件的情況下, 以動態、 透明的方式給單個物件新增職責。
要點:動態地為物件新增功能。不改變原類檔案。抽象裝飾器與具體被裝飾物件實現同一個介面。抽象裝飾器持有被裝飾器介面物件,以便請求傳遞。
舉例:機器人功能擴充套件。給人穿件衣服。java.util.Collections#checkedXXX()、synchronizedXXX()。Java的IO流,比如InputStream有各種FileInputStream,FilterInputStream等等(具體可以檢視類圖)。javax.servlet.http.HttpServletRequestWrapper 和 HttpServletResponseWrapper
/**
* 裝飾器模式之機器人功能升級案例
*/
public class DecoratorPattern {
public static void main(String[] args) {
new RobotDecorator(new FirstRobot()).doMoreThing();
}
}
interface Robot {
void doSomething();
}
/**
* 第一代機器人
*/
class FirstRobot implements Robot {
@Override
public void doSomething() {
System.out.println("唱歌");
System.out.println("對話");
}
}
/**
* 機器人裝飾器
* 定義為抽象類後,可以定義其子類去實現更多裝飾器(更靈活)
*/
class RobotDecorator implements Robot {
private Robot robot;
public RobotDecorator(Robot robot) {
this.robot = robot;
}
@Override
public void doSomething() {
this.robot.doSomething();
}
public void doMoreThing() {
this.robot.doSomething();
System.out.println("跳舞、拖地");
}
}
介面卡模式
概述:將一個類的介面變換成客戶端所期待的另一種介面,從而使原本介面不匹配而無法工作在一起的兩個類能夠在一起工作。
要點:Adapter and Adaptee ,關聯 or 繼承。不改變原來的介面,只提供轉換的作用。
舉例:翻譯者、InputStreamReader、Spring MVC
public class AdapterPattern {
public static void main(String[] args) {
System.out.println(new SpeakAdapter(new Speaker()).translate());
}
}
class Speaker {
public String speak() {
return "aba,aba";
}
}
interface Translate {
String translate();
}
class SpeakAdapter implements Translate {
private Speaker speaker;
public SpeakAdapter(Speaker speaker) {
this.speaker = speaker;
}
@Override
public String translate() {
String result = speaker.speak();
result = result.replace(',', ',');
// 適配過程,處理。。。
return result;
}
}
TODO
參考
https://space.bilibili.com/59546029/channel/detail?cid=134013 "子爍愛學習:提升篇—設計模式"
https://refactoringguru.cn/design-patterns/catalog "Refactoring.Guru"