什么是設計模式?
? ??設計模式是軟件工程中解決常見問題的經典方案,它們代表了最佳實踐和經驗總結。通過使用設計模式,開發者可以創建更加靈活、可維護和可擴展的代碼結構。設計模式不是具體的代碼實現,而是針對特定問題的通用解決方案模板,需要在特定上下文中適當應用。
設計模式的核心價值在于:
提供經過驗證的解決方案
促進代碼重用
提高代碼可讀性和可維護性
促進團隊之間的溝通
設計模式分為3類:
- 創建型模式:關注對象創建機制,增加創建對象的靈活性
- 結構型模式:關注類和對象的組合,形成更大的結構
- 行為型模式:關注對象之間的職責分配和通信
創建型模式
單例模式
意圖:確保一個類只有一個實例,并提供全局訪問點
適用場景:
當類只能有一個實例且客戶端可從眾所周知的訪問點訪問它時
當唯一實例應通過子類化擴展,且客戶端無需修改代碼就能使用擴展實例時
實現要點:
私有化構造函數
提供靜態方法獲取實例
考慮多線程環境下的安全性
示例
public class Singleton {// volatile確保多線程環境下的可見性private static volatile Singleton instance;private Singleton() {// 防止通過反射實例化if (instance != null) {throw new RuntimeException("Use getInstance() method to get the single instance of this class.");}}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
注意事項:
單例模式可能隱藏類之間的依賴關系
不利于單元測試
在分布式系統中可能需要調整
工廠方法模式
意圖:定義一個創建對象的接口,但讓子類決定實例化哪個類
適用場景:
當一個類不知道它需要創建哪些具體類的對象時
當一個類希望由其子類指定創建的對象時
結構:
Product:定義工廠方法創建的對象的接口
ConcreteProduct:實現Product接口的具體類
Creator:聲明工廠方法
ConcreteCreator:重寫工廠方法以返回ConcreteProduct實例
示例
// 產品接口
interface Button {void render();void onClick();
}// 具體產品 - HTML按鈕
class HtmlButton implements Button {@Overridepublic void render() {System.out.println("渲染HTML按鈕");}@Overridepublic void onClick() {System.out.println("HTML按鈕點擊事件");}
}// 具體產品 - Windows按鈕
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("渲染Windows按鈕");}@Overridepublic void onClick() {System.out.println("Windows按鈕點擊事件");}
}// 創建者基類
abstract class Dialog {// 工廠方法public abstract Button createButton();public void render() {Button button = createButton();button.render();button.onClick();}
}// 具體創建者 - HTML對話框
class HtmlDialog extends Dialog {@Overridepublic Button createButton() {return new HtmlButton();}
}// 具體創建者 - Windows對話框
class WindowsDialog extends Dialog {@Overridepublic Button createButton() {return new WindowsButton();}
}
抽象工廠模式
意圖:提供一個接口,用于創建相關或依賴對象的家族,而不需要指定具體類
適用場景:
系統需要獨立于其產品的創建、組合和表示時
系統需要配置多個產品系列中的一個時
需要強調一系列相關產品對象的設計以便進行聯合使用時
示例
// 抽象產品 - 按鈕
interface Button {void paint();
}// 抽象產品 - 復選框
interface Checkbox {void paint();
}// 具體產品 - Mac按鈕
class MacOSButton implements Button {@Overridepublic void paint() {System.out.println("繪制MacOS風格按鈕");}
}// 具體產品 - Windows按鈕
class WindowsButton implements Button {@Overridepublic void paint() {System.out.println("繪制Windows風格按鈕");}
}// 具體產品 - Mac復選框
class MacOSCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("繪制MacOS風格復選框");}
}// 具體產品 - Windows復選框
class WindowsCheckbox implements Checkbox {@Overridepublic void paint() {System.out.println("繪制Windows風格復選框");}
}// 抽象工廠
interface GUIFactory {Button createButton();Checkbox createCheckbox();
}// 具體工廠 - Mac工廠
class MacOSFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacOSButton();}@Overridepublic Checkbox createCheckbox() {return new MacOSCheckbox();}
}// 具體工廠 - Windows工廠
class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}// 客戶端代碼
class Application {private Button button;private Checkbox checkbox;public Application(GUIFactory factory) {button = factory.createButton();checkbox = factory.createCheckbox();}public void paint() {button.paint();checkbox.paint();}
}
建造者模式
意圖:將一個復雜對象的構建與其表示分離,使得同樣的構建過程可以創建不同的表示
適用場景:
當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時
當構造過程必須允許被構造的對象有不同的表示時
示例
// 最終產品
class Car {private String engine;private int seats;private boolean GPS;private boolean tripComputer;// 省略getter和setter方法public void display() {System.out.println("汽車配置:");System.out.println("引擎:" + engine);System.out.println("座位數:" + seats);System.out.println("GPS:" + (GPS ? "有" : "無"));System.out.println("行車電腦:" + (tripComputer ? "有" : "無"));}
}// 抽象建造者
interface CarBuilder {void reset();void setEngine(String engine);void setSeats(int seats);void setGPS(boolean hasGPS);void setTripComputer(boolean hasTripComputer);Car getResult();
}// 具體建造者
class SportsCarBuilder implements CarBuilder {private Car car;public SportsCarBuilder() {this.reset();}@Overridepublic void reset() {this.car = new Car();}@Overridepublic void setEngine(String engine) {car.setEngine(engine);}@Overridepublic void setSeats(int seats) {car.setSeats(seats);}@Overridepublic void setGPS(boolean hasGPS) {car.setGPS(hasGPS);}@Overridepublic void setTripComputer(boolean hasTripComputer) {car.setTripComputer(hasTripComputer);}@Overridepublic Car getResult() {Car product = this.car;this.reset();return product;}
}// 導演類
class Director {public void constructSportsCar(CarBuilder builder) {builder.reset();builder.setEngine("V8引擎");builder.setSeats(2);builder.setGPS(true);builder.setTripComputer(true);}public void constructSUV(CarBuilder builder) {builder.reset();builder.setEngine("V6引擎");builder.setSeats(7);builder.setGPS(true);builder.setTripComputer(false);}
}// 客戶端使用
public class BuilderDemo {public static void main(String[] args) {Director director = new Director();CarBuilder builder = new SportsCarBuilder();director.constructSportsCar(builder);Car car = builder.getResult();car.display();}
}
原型模式
意圖:用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象
適用場景:
當要實例化的類是在運行時指定時
當需要避免創建與產品類層次平行的工廠類層次時
當一個類的實例只能有幾個不同狀態組合中的一種時
示例
// 原型接口
interface Prototype {Prototype clone();String getName();void setName(String name);
}// 具體原型
class ConcretePrototype implements Prototype {private String name;public ConcretePrototype(String name) {this.name = name;}@Overridepublic Prototype clone() {return new ConcretePrototype(this.name);}@Overridepublic String getName() {return name;}@Overridepublic void setName(String name) {this.name = name;}
}// 客戶端使用
public class PrototypeDemo {public static void main(String[] args) {ConcretePrototype original = new ConcretePrototype("原始對象");System.out.println("原始對象名稱: " + original.getName());ConcretePrototype cloned = (ConcretePrototype) original.clone();cloned.setName("克隆對象");System.out.println("原始對象名稱: " + original.getName());System.out.println("克隆對象名稱: " + cloned.getName());}
}
:)