設計模式1:創建型模式
設計模式2:結構型模式(編寫中)
設計模式3:行為型模式(編寫中)
前言
設計模式是軟件開發中經過驗證的可復用解決方案,它們源自實踐、提煉于經驗,并在面向對象編程中扮演著關鍵角色。GoF(Gang of Four)設計模式分為創建型、結構型和行為型三大類,共23種。設計模式的核心價值在于提高代碼的可維護性、可擴展性和可復用性,同時遵循軟件設計原則。
本文介紹創建型模式。創建型模式關注對象的創建過程,通過將對象的創建與使用分離,使系統能夠靈活地控制對象的生成方式。
1 單例模式(Singleton)
單例模式確保一個類只有一個實例,并提供一個全局訪問點。它適用于需要嚴格控制實例數量的場景,如全局配置、數據庫連接池和日志系統等。
核心思想:通過私有構造函數限制外部實例化,使用靜態變量保存唯一實例,并通過靜態方法提供全局訪問。
Java實現:
public class President {private static President instance; // 唯一private President() {} // 禁止外部newpublic static President getInstance() { if (instance == null) { instance = new President(); // 延遲初始化 } return instance; }
}// 使用示例
President p1 = President.getInstance();
President p2 = President.getInstance();
System.out.println(p1 == p2); // true(同一個)
適用場景:需要全局唯一訪問點的場景,如配置管理、資源共享等。
優點:節省內存,避免重復創建;提供全局訪問點。
缺點:多線程環境下需加鎖(可用雙重檢查鎖優化);破壞了單一職責原則。
2 工廠方法模式(Factory Method)
工廠方法模式定義一個創建對象的接口,但由子類決定實例化哪一個類,將實例化延遲到子類。它適用于需要解耦對象創建與使用,同時允許擴展的場景。
核心思想:通過抽象工廠類定義創建對象的方法,具體實現由子類完成,遵循開閉原則。
Java實現:
// 抽象產品類
interface Transport { void deliver();
}
// 具體產品類
class Truck implements Transport { public void deliver() { System.out.println(“陸運”); }
}
class Ship implements Transport { public void deliver() { System.out.println(“海運”); }
}
// 抽象工廠類
interface Logistics { Transport createTransport();
}
// 具體工廠類
class RoadLogistics implements Logistics { public Transport createTransport() { return new Truck(); }
}
class SeaLogistics implements Logistics { public Transport createTransport() { return new Ship(); }
}// 使用示例
Logistics roadLogistics = new RoadLogistics();
Transport truck = roadLogistics.createTransport();
truck.deliver();
適用場景:對象創建邏輯復雜(如依賴配置、外部服務),需解耦對象創建與使用 。
優點:擴展性強,新增產品只需添加子類;遵循開閉原則。
缺點:每新增一個產品就要新增一個工廠類;類層次結構可能變得復雜。
3 抽象工廠模式(Abstract Factory)
抽象工廠模式提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們的具體類。它適用于需要創建多個相關對象家族的場景。
核心思想:通過工廠接口定義一組產品對象的創建方法,具體實現由子類完成,實現產品家族的統一創建。
Java實現:
// 產品接口
interface Phone { void call();
}
interface Earphone { void play();
}
// 蘋果產品家族
class iPhone implements Phone { public void call() { System.out.println(“iPhone通話”); }
}
class AirPods implements Earphone { public void play() { System.out.println(“AirPods播放”); }
}
// 小米產品家族
class MiPhone implements Phone { public void call() { System.out.println(“小米手機通話”); }
}
class MiEarphone implements Earphone { public void play() { System.out.println(“小米耳機播放”); }
}
// 抽象工廠接口
interface TechFactory { Phone createPhone(); Earphone createEarphone();
}
// 具體工廠類
class AppleFactory implements TechFactory { public Phone createPhone() { return new iPhone(); }public Earphone createEarphone() { return new AirPods(); }
}
class MiFactory implements TechFactory { public Phone createPhone() { return new MiPhone(); }public Earphone createEarphone() { return new MiEarphone(); }
}// 使用示例
TechFactory factory = new AppleFactory();
Phone phone = factory.createPhone();
Earphone earphone = factory.createEarphone();
phone.call(); // iPhone通話
earphone.play(); // AirPods播放
適用場景:跨平臺應用(如Windows/macOS按鈕)、產品線擴展等。
優點:產品族統一創建,保證一致性;擴展性強,新增產品族只需添加子類。
缺點:工廠類數量隨產品族增加而增加;難以支持產品族的動態切換。
4 建造者模式(Builder)
建造者模式將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。它適用于需要構建復雜對象,且對象的構建過程可能變化的場景。
核心思想:通過建造者類逐步構建對象,最后通過build方法返回完整對象;使用導演類控制構建過程。
Java實現:
// 奶茶產品類
class BubbleTea { private String size; private boolean ice; private List toppings;// 私有構造函數 private BubbleTea(Builder builder) { this.size = builder.size; this.ice = builder.ice; this.toppings = builder.toppings; }// 獲取建造者 public static class Builder { private String size = “中杯”; private boolean ice = true; private List toppings = new ArrayList<>();public Builder size(String size) { this.size = size; return this; }public Builder ice(boolean ice) { this.ice = ice; return this; }public Builder addTopping(Topping topping) { toppings.add(topping); return this; }public BubbleTea build() { return new BubbleTea(this); } }// 配料枚舉 enum Topping { 波霸, 珍珠, 椰果, 西米 }
}// 使用示例
BubbleTea bubbleTea = new BubbleTea.Builder() .size(“大杯”) .ice(false) .addTopping(BubbleTea.Topping.波霸) .addTopping(BubbleTea.Topping.珍珠) .build();
System.out.println(“奶茶規格:” + bubbleTea.size);
System.out.println(“是否加冰:” + (bubbleTea.ice ? “是” : “否”));
System.out.println(“配料:” + bubbleTea.toppings);
適用場景:構建復雜對象(如訂單、配置文件)、參數較多的構造函數等。
優點:參數解耦,構建過程清晰;支持部分構建和鏈式調用。
缺點:類數量增加;過度使用可能增加代碼復雜度。
5 原型模式(Prototype)
原型模式通過復制現有對象來創建新對象,避免重復初始化。它適用于對象創建成本高,或需要快速復制已有對象的場景。
核心思想:通過克隆方法復制對象,創建新實例;使用深拷貝或淺拷貝控制復制深度。
Java實現:
// 原型接口
interface Shape extends Cloneable { void draw(); Shape clone();
}
// 具體形狀類
class Circle implements Shape { private String color;public Circle(String color) { this.color = color; }public void draw() { System.out.println(“繪制圓形,顏色:” + color); }@Override public Shape clone() { try { return (Shape) super.clone(); } catch (CloneException e) { throw new RuntimeException(e); } }
}
class Square implements Shape { private int sideLength;public Square(int sideLength) { this.sideLength = sideLength; }public void draw() { System.out.println(“繪制正方形,邊長:” + sideLength); }@Override public Shape clone() { try { return (Shape) super.clone(); } catch (CloneException e) { throw new RuntimeException(e); } }
}// 使用示例
Circle circle = new Circle(“紅色”);
Shape circleClone = circle.clone();
circleClone.draw(); // 繪制圓形,顏色:紅色
適用場景:對象創建成本高(如數據庫連接、圖形對象)、需要快速復制已有對象等 [3]。
優點:性能高效,避免重復初始化;代碼簡潔,直接使用克隆方法 [3]。
缺點:深拷貝實現復雜;不適合不可克隆的對象。
6 對象池模式(Object Pool)
對象池模式是單例模式的擴展,通過預先創建并管理對象集合,減少頻繁創建/銷毀的開銷 。它適用于資源密集型對象(如數據庫連接、網絡套接字)的高效復用場景。
核心思想:通過對象池管理對象的生命周期,包括對象的分配、重用和釋放;使用工廠模式創建和銷毀對象 。
Java實現:
// 池化對象接口
interface PoolableObject { void activate(); // 激活對象 void passivate(); // 使對象空閑
}
// 對象池接口
interface ObjectPool { T borrowObject(); // 獲取對象 void returnObject(T obj); // 歸還對象 void clear(); // 清除池中對象
}
// 對象池工廠接口
interface PoolableObjectFactory { T makeObject(); // 創建對象 void destroyObject(T obj); // 銷毀對象 void activateObject(T obj); // 激活對象 void passivateObject(T obj); // 使對象空閑
}
// 具體實現
class SimpleObjectPool implements ObjectPool {private final PoolableObjectFactory factory; private final List pool = new ArrayList<>(); private final int maxPoolSize;public SimpleObjectPool(PoolableObjectFactory factory, int maxPoolSize) { this.factory = factory; this.maxPoolSize = maxPoolSize; // 初始化池 for (int i = 0; i < maxPoolSize; i++) { T obj = factory.makeObject(); obj.passivate(); pool.add(obj); } }@Override public T borrowObject() { // 獲取空閑對象 for (T obj : pool) { if (!obj.isActive()) { obj.activate(); return obj; }} // 如果池已滿,可能需要創建新對象 if (pool.size() < maxPoolSize) { T obj = factory.makeObject(); obj.activate(); pool.add(obj); return obj; } // 池已滿,無法獲取對象 return null; }@Override public void returnObject(T obj) { if (pool.contains(obj)) { obj.passivate(); } else { // 可能需要處理不屬于池的對象 factory.destroyObject(obj); } }@Override public void clear() { for (T obj : pool) { factory.destroyObject(obj); } pool.clear(); }
}
// 使用示例
// 定義池化對象
class DatabaseConnection implements PoolableObject { private boolean active = false;public void activate() { this.active = true; System.out.println(“連接激活”); }public void passivate() { this.active = false; System.out.println(“連接空閑”); }public boolean.isActive() { return active; }public void connect() { System.out.println(“建立數據庫連接”); }public void disconnect() { System.out.println(“關閉數據庫連接”); }
}
// 定義工廠
class DatabaseConnectionFactory implements PoolableObjectFactory { @Override public DatabaseConnection makeObject() { return new DatabaseConnection(); }@Override public void destroyObject(DatabaseConnection obj) { obj.disconnect(); }@Override public void activateObject(DatabaseConnection obj) { obj.activate(); }@Override public void passivateObject(DatabaseConnection obj) { obj.passivate(); }
}
// 使用對象池
ObjectPool pool = new SimpleObjectPool<>(new DatabaseConnectionFactory(), 10);
DatabaseConnection conn = pool borrowObject();
// 使用連接
conn.connect();
// 歸還連接
pool.returnObject(conn);
適用場景:資源密集型對象(如數據庫連接、網絡套接字、游戲中的粒子系統)的高效復用。
優點:減少對象創建和銷毀的開銷;提高系統性能。
缺點:增加系統復雜度;管理池對象需要額外資源。