1. 程式人生 > 實用技巧 >設計模式學習總結(Java版)

設計模式學習總結(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()、synchronized­XXX()。Java的IO流,比如InputStream有各種FileInputStream,FilterInputStream等等(具體可以檢視類圖)。javax.servlet.http.HttpServletRequestWrapper 和 Http­Servlet­Response­Wrapper

/**
 * 裝飾器模式之機器人功能升級案例
 */
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"