一、設計模式核心分類
設計模式分為?3 大類,共?23 種模式(考試常考約?10-15 種):
分類 | 核心模式 | 考試重點 |
---|---|---|
創建型模式 | 工廠方法、抽象工廠、單例、生成器、原型 | 單例模式的實現(懶漢、餓漢)、工廠模式的應用場景 |
結構型模式 | 適配器、代理、裝飾器、組合、外觀、橋接 | 適配器與代理的區別、裝飾器模式的動態擴展特性 |
行為型模式 | 觀察者、策略、模板方法、職責鏈、狀態、迭代器、備忘錄、中介者、解釋器 | 觀察者模式的事件驅動、策略模式的算法替換、模板方法的流程固定步驟可擴展特性 |
二、設計模式分類(GoF 23種模式)
考試重點通常集中在以下分類及典型模式:
1. 創建型模式
核心:對象實例化的靈活控制。
1. 工廠方法模式(Factory Method)
-
定義:
定義一個創建對象的接口,但由子類決定具體實例化的類。 -
類圖結構:
-
抽象工廠類(Creator):聲明工廠方法(如
createProduct()
)。 -
具體工廠類(ConcreteCreator):實現工廠方法,返回具體產品對象。
-
抽象產品類(Product):定義產品的接口。
-
具體產品類(ConcreteProduct):實現產品接口。
-
-
應用場景:
-
日志記錄器(不同格式的日志:文件、數據庫)。
-
數據庫連接(不同數據庫驅動:MySQL、Oracle)。
-
-
優點:
-
符合開閉原則,新增產品只需擴展子類。
-
客戶端代碼與具體產品解耦。
-
-
代碼示例(Java):
interface Product { void use(); } class ConcreteProductA implements Product { public void use() { /*...*/ } } abstract class Creator {public void operation() {Product p = createProduct();p.use();}abstract Product createProduct(); } class ConcreteCreatorA extends Creator {public Product createProduct() { return new ConcreteProductA(); } }
2. 抽象工廠模式(Abstract Factory)
-
定義:
提供一個接口,用于創建相關或依賴對象的家族,而無需指定具體類。 -
類圖結構:
-
抽象工廠接口(AbstractFactory):聲明一組創建產品的方法(如
createButton()
,?createTextBox()
)。 -
具體工廠類(ConcreteFactory):實現接口,生成同一產品族的具體對象。
-
抽象產品接口(Button, TextBox):定義產品的功能。
-
具體產品類(WindowsButton, MacButton):實現不同平臺的組件。
-
-
與工廠方法的區別:
-
工廠方法:針對單一產品等級結構。
-
抽象工廠:針對多個產品等級結構(產品族)。
-
-
缺點:
-
擴展新產品族困難(需修改抽象工廠接口)。
-
3. 單例模式(Singleton)
-
定義:
保證一個類只有一個實例,并提供它的全局訪問點。 -
實現要點:
-
私有構造函數。
-
靜態成員變量保存唯一實例。
-
提供靜態方法獲取實例(如
getInstance()
)。
-
-
線程安全實現:
-
雙重檢查鎖(DCL)(適用于Java/C#):
public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;} }
-
靜態內部類(延遲加載且線程安全):
public class Singleton {private Singleton() {}private static class Holder {static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return Holder.INSTANCE;} }
-
4. 生成器模式(Builder)
-
定義:
將一個復雜對象的構造過程與表示分離,使得同樣的構建過程可以創建不同的表示。 -
類圖結構:
-
抽象建造者(Builder):定義構建步驟的抽象接口(如
buildPartA()
,?buildPartB()
)。 -
具體建造者(ConcreteBuilder):實現構建步驟,提供獲取結果的接口。
-
指揮者(Director):構造一個使用Builder接口的對象。
-
產品(Product):最終構建的復雜對象。
-
-
應用場景:
-
生成復雜對象(如XML文檔、HTML報表)。
-
創建具有多個可選參數的對象(避免構造函數參數爆炸)。
-
-
代碼示例(簡化版):
class Computer {private String cpu;private String ram;// 構造函數私有,只能通過Builder創建private Computer(Builder builder) { /*...*/ }static class Builder {private String cpu;private String ram;public Builder setCpu(String cpu) { this.cpu = cpu; return this; }public Builder setRam(String ram) { this.ram = ram; return this; }public Computer build() { return new Computer(this); }} } // 使用方式 Computer computer = new Computer.Builder().setCpu("i7").setRam("16GB").build();
5. 原型模式(Prototype)
-
定義:
用原型實例指定創建對象的種類,并且通過復制這些原型創建新的對象。 -
實現要點:
-
實現
Cloneable
接口(Java)或深拷貝邏輯。 -
提供
clone()
方法(淺拷貝需謹慎處理引用類型)。
-
-
應用場景:
-
對象創建成本較高(如數據庫查詢結果緩存后復制)。
-
需要動態配置對象屬性(如游戲中的敵人克隆)。
-
-
深拷貝 vs 淺拷貝:
-
淺拷貝:復制基本類型字段,引用類型字段共享同一對象。
-
深拷貝:引用類型字段也遞歸復制。
-
-
代碼示例(Java):
class Prototype implements Cloneable {private List<String> list = new ArrayList<>();@Overridepublic Prototype clone() {try {Prototype copy = (Prototype) super.clone();copy.list = new ArrayList<>(this.list); // 深拷貝listreturn copy;} catch (CloneNotSupportedException e) {return null;}} }
2. 結構型模式
核心:通過組合類或對象形成更大結構。
1. 適配器模式(Adapter)
-
定義:將一個類的接口轉換成客戶希望的另一個接口。
-
實現方式:
-
類適配器:通過繼承適配者類實現目標接口。
-
對象適配器:通過組合適配者對象實現目標接口。
-
-
應用場景:
-
整合第三方庫(如不同格式的日志接口轉換)。
-
舊系統接口升級兼容。
-
-
代碼示例:
// 目標接口 interface Target { void request(); }// 適配者類 class Adaptee { void specificRequest() { /*...*/ } }// 對象適配器 class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) { this.adaptee = adaptee; }public void request() { adaptee.specificRequest(); } }
2. 裝飾器模式(Decorator)
-
定義:動態地為對象添加額外職責,避免子類膨脹。
-
結構:
-
組件接口(Component):定義一個對象接口,可以對這些對象動態地添加職責。
-
具體組件(ConcreteComponent):定義一個對象,可以對這個對象添加一些職責。
-
裝飾器基類(Decorator):繼承組件接口,持有組件實例。
-
具體裝飾器(ConcreteDecorator):添加附加功能。
-
-
應用場景:
-
Java I/O流(如
BufferedInputStream
裝飾FileInputStream
)。 -
動態擴展對象行為(如為訂單添加折扣、稅費計算)。
-
-
代碼示例:
interface Coffee { double getCost(); } class SimpleCoffee implements Coffee { public double getCost() { return 10; } }abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) { this.coffee = coffee; } }class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) { super(coffee); }public double getCost() { return coffee.getCost() + 2; } }
3. 代理模式(Proxy)
-
定義:為其他對象提供一種代理以控制對這個對象的訪問。
-
類型:
-
虛擬代理:延遲加載(如圖片懶加載)。
-
保護代理:控制訪問權限。
-
遠程代理:跨網絡訪問對象(如RPC)。
-
-
應用場景:
-
Spring AOP中的動態代理(JDK動態代理、CGLIB)。
-
訪問敏感資源時的權限校驗。
-
-
代碼示例:
interface Image { void display(); }class RealImage implements Image {public RealImage(String filename) { loadFromDisk(); }private void loadFromDisk() { /* 耗時操作 */ }public void display() { /* 顯示圖片 */ } }class ProxyImage implements Image {private RealImage realImage;private String filename;public ProxyImage(String filename) { this.filename = filename; }public void display() {if (realImage == null) realImage = new RealImage(filename);realImage.display();} }
4. 組合模式(Composite)
-
定義:將對象組合成樹形結構以表示“部分-整體”層次,使客戶端統一處理單個對象和組合對象。
-
結構:
-
組件接口(Component):定義葉子節點和容器的公共操作(如
add()
,?remove()
)。 -
葉子節點(Leaf):無子節點,實現基礎操作。
-
復合節點(Composite):包含子組件,管理子組件集合。
-
-
應用場景:
-
文件系統(文件與文件夾的統一操作)。
-
GUI容器控件(如Panel包含Button、Label等)。
-
-
代碼示例:
interface FileSystemComponent {void display(); }class File implements FileSystemComponent {public void display() { System.out.println("顯示文件"); } }class Folder implements FileSystemComponent {private List<FileSystemComponent> children = new ArrayList<>();public void add(FileSystemComponent cmp) { children.add(cmp); }public void display() {for (FileSystemComponent cmp : children) cmp.display();} }
5. 外觀模式(Facade)
-
定義:為子系統中的一組接口提供一個一致的界面,簡化客戶端調用。
-
應用場景:
-
復雜API的簡化封裝(如支付系統的統一入口)。
-
微服務網關聚合多個服務接口。
-
-
代碼示例:
class SubsystemA { void operationA() { /*...*/ } } class SubsystemB { void operationB() { /*...*/ } }class Facade {private SubsystemA a = new SubsystemA();private SubsystemB b = new SubsystemB();public void simplifiedOperation() {a.operationA();b.operationB();} }
6. 享元模式(Flyweight)
-
定義:運用共享技術有效地支持大量細粒度的對象。
-
關鍵點:
-
內部狀態:可共享的部分(如字符的Unicode值)。
-
外部狀態:不可共享的部分(如字符的位置、顏色)。
-
-
應用場景:
-
文本編輯器中的字符對象池。
-
游戲中的粒子系統(共享粒子類型,外部傳入位置和速度)。
-
-
代碼示例:
class Flyweight {private String intrinsicState; // 內部狀態public Flyweight(String intrinsicState) { this.intrinsicState = intrinsicState; }public void operation(String extrinsicState) { /*...*/ } }class FlyweightFactory {private Map<String, Flyweight> pool = new HashMap<>();public Flyweight getFlyweight(String key) {if (!pool.containsKey(key)) pool.put(key, new Flyweight(key));return pool.get(key);} }
7. 橋接模式(Bridge)
-
定義:將抽象部分與實現部分分離,使它們可以獨立變化。
-
結構:
-
抽象化(Abstraction):定義高層控制邏輯。
-
擴展抽象化(RefinedAbstraction):擴展抽象邏輯。
-
實現者(Implementor):定義底層實現接口。
-
具體實現者(ConcreteImplementor):實現具體功能。
-
-
應用場景:
-
跨平臺圖形渲染(如不同操作系統的繪圖API)。
-
消息發送方式(郵件、短信)與內容類型的解耦。
-
-
代碼示例:
interface Renderer { void renderCircle(float radius); } class VectorRenderer implements Renderer { /* 矢量渲染 */ } class RasterRenderer implements Renderer { /* 柵格渲染 */ }abstract class Shape {protected Renderer renderer;public Shape(Renderer renderer) { this.renderer = renderer; }abstract void draw(); }class Circle extends Shape {private float radius;public Circle(Renderer renderer, float radius) { super(renderer); this.radius = radius; }void draw() { renderer.renderCircle(radius); } }
3. 行為型模式
核心:對象間的通信與職責分配。
1. 模板方法模式(Template Method)
-
定義:
定義算法的骨架,將某些步驟延遲到子類實現,使得子類可以不改變算法結構即可重定義某些步驟。 -
結構:
-
抽象類(AbstractClass):定義模板方法(
final
修飾)和抽象步驟方法(如primitiveStep1()
)。 -
具體子類(ConcreteClass):實現抽象步驟。
-
-
應用場景:
-
框架設計(如Spring的
JdbcTemplate
)。 -
統一流程控制(如訂單處理流程:驗證→支付→發貨)。
-
-
代碼示例:
abstract class AbstractClass {public final void templateMethod() { // 模板方法step1();step2(); // 抽象步驟}void step1() { /* 默認實現 */ }abstract void step2(); }class ConcreteClass extends AbstractClass {void step2() { /* 子類實現 */ } }
2. 策略模式(Strategy)
-
定義:定義算法族,封裝每個算法,使其可互相替換,讓算法的變化獨立于使用它的客戶端。
-
結構:
-
策略接口(Strategy):定義算法方法(如
execute()
)。 -
具體策略類(ConcreteStrategy):實現不同算法。
-
上下文類(Context):持有策略對象并調用其算法。
-
-
應用場景:
-
支付方式選擇(支付寶、微信支付等)。
-
排序算法切換(冒泡排序、快速排序)。
-
-
代碼示例:
interface PaymentStrategy { void pay(int amount); }class AlipayStrategy implements PaymentStrategy {public void pay(int amount) { /* 支付寶支付邏輯 */ } }class Context {private PaymentStrategy strategy;public void setStrategy(PaymentStrategy strategy) { this.strategy = strategy; }public void executePay(int amount) { strategy.pay(amount); } }
3. 觀察者模式(Observer)
-
定義:定義對象間的一對多依賴關系,當一個對象(主題)狀態改變時,所有依賴它的對象(觀察者)自動收到通知并更新。
-
結構:
-
主題接口(Subject):提供注冊、刪除、通知觀察者的方法。
-
具體主題(ConcreteSubject):維護觀察者列表,狀態改變時通知所有觀察者。
-
觀察者接口(Observer):定義更新方法(如
update()
)。 -
具體觀察者(ConcreteObserver):實現更新邏輯。
-
-
應用場景:
-
事件驅動系統(如GUI按鈕點擊事件)。
-
發布-訂閱模型(如消息隊列)。
-
-
代碼示例:
interface Observer { void update(String message); }class ConcreteObserver implements Observer {public void update(String message) { /* 處理消息 */ } }class Subject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer o) { observers.add(o); }public void notifyObservers(String message) {for (Observer o : observers) o.update(message);} }
4. 責任鏈模式(Chain of Responsibility)
-
定義:使多個對象有機會處理請求,從而避免請求的發送者和接受者之前的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
-
結構:
-
處理器接口(Handler):定義處理請求的方法和設置下一個處理器的鏈接方法。
-
具體處理器(ConcreteHandler):實現處理邏輯,決定是否處理請求或傳遞給下一個處理器。
-
-
應用場景:
-
審批流程(如請假審批:組長→經理→CEO)。
-
異常處理鏈(如Spring MVC的攔截器)。
-
-
代碼示例:
abstract class Handler {protected Handler next;public void setNext(Handler next) { this.next = next; }public abstract void handleRequest(Request request); }class ManagerHandler extends Handler {public void handleRequest(Request request) {if (canHandle(request)) { /* 處理 */ } else if (next != null) next.handleRequest(request);} }
5. 命令模式(Command)
-
定義:將請求封裝為對象,以便支持請求的排隊、記錄、撤銷等操作。
-
結構:
-
命令接口(Command):聲明執行方法(如
execute()
)。 -
具體命令(ConcreteCommand):綁定接收者對象并調用其方法。
-
調用者(Invoker):觸發命令執行(如按鈕點擊)。
-
接收者(Receiver):實際執行操作的對象。
-
-
應用場景:
-
圖形界面菜單操作(撤銷、重做)。
-
任務隊列調度(如線程池任務提交)。
-
-
代碼示例:
interface Command { void execute(); }class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) { this.light = light; }public void execute() { light.on(); } }class RemoteControl { // Invokerprivate Command command;public void setCommand(Command cmd) { this.command = cmd; }public void pressButton() { command.execute(); } }
6. 狀態模式(State)
-
定義:允許對象在其內部狀態改變時改變行為,將狀態相關的邏輯封裝到獨立的狀態類中。
-
結構:
-
狀態接口(State):定義狀態行為方法(如
handle()
)。 -
具體狀態類(ConcreteState):實現不同狀態下的行為。
-
上下文類(Context):持有狀態對象,委托狀態處理請求。
-
-
應用場景:
-
訂單狀態流轉(待支付→已發貨→已完成)。
-
游戲角色狀態(正常、中毒、眩暈)。
-
-
代碼示例:
interface State { void handle(Context context); }class ConcreteStateA implements State {public void handle(Context context) { context.setState(new ConcreteStateB());} }class Context {private State state;public void setState(State state) { this.state = state; }public void request() { state.handle(this); } }
7.解釋器模式(Interpreter)
- 定義:給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
- 代碼示例:
// 抽象表達式 interface Expression {int interpret(Context context); }// 終結符表達式:數字 class Number implements Expression {private int value;public Number(int value) { this.value = value; }public int interpret(Context context) { return value; } }// 非終結符表達式:加法 class Add implements Expression {private Expression left;private Expression right;public Add(Expression left, Expression right) {this.left = left;this.right = right;}public int interpret(Context context) {return left.interpret(context) + right.interpret(context);} }// 非終結符表達式:乘法 class Multiply implements Expression {private Expression left;private Expression right;public Multiply(Expression left, Expression right) {this.left = left;this.right = right;}public int interpret(Context context) {return left.interpret(context) * right.interpret(context);} }// 上下文(此處簡單實現,無額外狀態) class Context {}// 客戶端構建語法樹并解釋 public class Client {public static void main(String[] args) {// 表達式:1 + 2 * 3Expression expr = new Add(new Number(1),new Multiply(new Number(2), new Number(3)));Context context = new Context();System.out.println(expr.interpret(context)); // 輸出:7} }
8. 中介者模式(Mediator Pattern)
定義:
中介者模式通過引入一個中介對象來封裝一組對象之間的交互,減少對象間的直接依賴,使交互變得松散耦合。結構:
-
Mediator(中介者接口):定義對象間通信的接口。
-
ConcreteMediator(具體中介者):協調各對象間的交互,維護對同事對象的引用。
-
Colleague(同事類接口):定義同事對象的通用接口,每個同事對象知道其中介者。
-
ConcreteColleague(具體同事類):實現同事接口,通過中介者與其他同事通信。
-
對象間存在復雜的網狀依賴關系(如GUI組件間的交互)。
-
需要集中控制多個對象間的通信邏輯。
代碼示例(Java):
interface Mediator {void notify(Colleague sender, String event);
}class ChatRoom implements Mediator {private List<Colleague> users = new ArrayList<>();public void addUser(Colleague user) { users.add(user); }@Overridepublic void notify(Colleague sender, String message) {for (Colleague user : users) {if (user != sender) user.receive(message);}}
}abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) { this.mediator = mediator; }abstract void send(String message);abstract void receive(String message);
}class User extends Colleague {public User(Mediator mediator) { super(mediator); }@Overridepublic void send(String message) {System.out.println("發送消息: " + message);mediator.notify(this, message);}@Overridepublic void receive(String message) {System.out.println("接收消息: " + message);}
}// 客戶端使用
public class Client {public static void main(String[] args) {ChatRoom chatRoom = new ChatRoom();User alice = new User(chatRoom);User bob = new User(chatRoom);chatRoom.addUser(alice);chatRoom.addUser(bob);alice.send("你好!"); // Bob接收消息}
}
9.備忘錄模式(Memento Pattern)
定義:
備忘錄模式在不破壞封裝性的前提下,捕獲對象的內部狀態并保存,以便后續恢復。
結構:
-
Originator(原發器):需要保存狀態的對象,提供創建備忘錄和恢復狀態的方法。
-
Memento(備忘錄):存儲原發器的狀態(通常為不可變對象)。
-
Caretaker(管理者):負責保存和恢復備忘錄,但不操作其內容。
適用場景:
-
需要實現撤銷/重做功能(如文本編輯器的撤銷操作)。
-
保存對象的歷史狀態用于回滾(如游戲存檔)。
代碼示例(Java):
// 原發器
class TextEditor {private String content;public void setContent(String content) { this.content = content; }public String getContent() { return content; }public Memento save() { return new Memento(content); }public void restore(Memento memento) { this.content = memento.getContent(); }
}// 備忘錄
class Memento {private final String content;public Memento(String content) { this.content = content; }public String getContent() { return content; }
}// 管理者
class History {private List<Memento> mementos = new ArrayList<>();public void push(Memento memento) { mementos.add(memento); }public Memento pop() { return mementos.remove(mementos.size() - 1); }
}// 客戶端使用
public class Client {public static void main(String[] args) {TextEditor editor = new TextEditor();History history = new History();editor.setContent("Version 1");history.push(editor.save());editor.setContent("Version 2");history.push(editor.save());editor.restore(history.pop()); // 回退到Version 1System.out.println(editor.getContent());}
}
10.訪問者模式(Visitor Pattern)
定義:
訪問者模式將作用于對象結構的操作與對象本身分離,允許在不修改對象結構的前提下定義新操作。
結構:
-
Visitor(訪問者接口):聲明訪問對象結構中各元素的方法(如
visitElementA()
)。 -
ConcreteVisitor(具體訪問者):實現訪問者接口,定義具體操作。
-
Element(元素接口):定義接受訪問者的方法(
accept(Visitor visitor)
)。 -
ConcreteElement(具體元素):實現元素接口,調用訪問者的對應方法。
-
ObjectStructure(對象結構):維護元素集合,提供遍歷接口。
適用場景:
-
需要對復雜對象結構進行多種獨立操作(如編譯器語法樹分析)。
-
避免污染元素類的代碼(如統計功能與業務邏輯分離)。
代碼示例(Java):
interface Visitor {void visit(ElementA element);void visit(ElementB element);
}class ConcreteVisitor implements Visitor {@Overridepublic void visit(ElementA element) {System.out.println("處理ElementA: " + element.operationA());}@Overridepublic void visit(ElementB element) {System.out.println("處理ElementB: " + element.operationB());}
}interface Element {void accept(Visitor visitor);
}class ElementA implements Element {public String operationA() { return "操作A"; }@Overridepublic void accept(Visitor visitor) { visitor.visit(this); }
}class ElementB implements Element {public String operationB() { return "操作B"; }@Overridepublic void accept(Visitor visitor) { visitor.visit(this); }
}// 客戶端使用
public class Client {public static void main(String[] args) {List<Element> elements = Arrays.asList(new ElementA(), new ElementB());Visitor visitor = new ConcreteVisitor();for (Element element : elements) {element.accept(visitor);}}
}
11.迭代器模式(Iterator Pattern)
定義:迭代器模式是一種行為型設計模式,提供一種方法順序訪問聚合對象中的元素,而無需暴露其底層表示。核心思想是將遍歷邏輯從聚合對象中分離,實現數據存儲與遍歷解耦。
-
Aggregate(聚合接口):聲明
createIterator()
方法,返回一個迭代器對象。 -
ConcreteAggregate(具體聚合類):實現聚合接口,返回與自身數據結構匹配的具體迭代器實例(如
new ConcreteIterator(this)
)。 -
Iterator(迭代器接口):定義遍歷方法:
-
hasNext()
:判斷是否還有下一個元素。 -
next()
:移動游標并返回當前元素。 -
currentItem()
(可選):直接獲取當前元素,不移動游標。
-
-
ConcreteIterator(具體迭代器):實現迭代器接口,維護當前遍歷位置(如
currentIndex
),并與聚合對象交互以訪問元素。