【2】23个设计模式精讲全集_下册
第13章 状态模式(State)- 行为型
核心一句话:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
🏠 生活真实故事
电梯有四种状态:
-
开门状态:可以上下人,不能运行
-
关门状态:可以运行,不能上下人
-
运行状态:正在上下楼,不能开门
-
停止状态:电梯停止,等待指令
在不同的状态下,电梯对同一个操作有不同的反应:
-
在开门状态下按"关门"按钮,电梯会关门
-
在关门状态下按"关门"按钮,电梯没有反应
-
在运行状态下按"开门"按钮,电梯没有反应
-
在停止状态下按"楼层"按钮,电梯会运行到指定楼层
如果不用状态模式,你需要写大量的if-else来判断电梯当前的状态,代码会非常臃肿。
📚 文科类比
-
人的情绪状态:人在开心、生气、悲伤等不同情绪下,对同一件事的反应不同
-
订单状态:订单有已下单、已支付、已发货、已完成、已取消等状态,不同状态下可以执行的操作不同
-
交通信号灯状态:红灯停、绿灯行、黄灯等一等
-
手机状态:手机有开机、关机、锁屏、飞行模式等状态,不同状态下可以执行的操作不同
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象状态类 ==============
abstract class ElevatorState {
protected Elevator elevator;
public ElevatorState(Elevator elevator) {
this.elevator = elevator;
}
public abstract void openDoor();
public abstract void closeDoor();
public abstract void run();
public abstract void stop();
}
// ============== 具体状态类 ==============
class OpenState extends ElevatorState {
public OpenState(Elevator elevator) {
super(elevator);
}
@Override
public void openDoor() {
System.out.println("电梯门已经是打开状态");
}
@Override
public void closeDoor() {
System.out.println("电梯门关闭");
elevator.setState(elevator.getCloseState());
}
@Override
public void run() {
System.out.println("电梯门打开,不能运行");
}
@Override
public void stop() {
System.out.println("电梯已经停止");
}
}
class CloseState extends ElevatorState {
public CloseState(Elevator elevator) {
super(elevator);
}
@Override
public void openDoor() {
System.out.println("电梯门打开");
elevator.setState(elevator.getOpenState());
}
@Override
public void closeDoor() {
System.out.println("电梯门已经是关闭状态");
}
@Override
public void run() {
System.out.println("电梯开始运行");
elevator.setState(elevator.getRunState());
}
@Override
public void stop() {
System.out.println("电梯已经停止");
}
}
class RunState extends ElevatorState {
public RunState(Elevator elevator) {
super(elevator);
}
@Override
public void openDoor() {
System.out.println("电梯正在运行,不能开门");
}
@Override
public void closeDoor() {
System.out.println("电梯门已经关闭");
}
@Override
public void run() {
System.out.println("电梯正在运行");
}
@Override
public void stop() {
System.out.println("电梯停止运行");
elevator.setState(elevator.getStopState());
}
}
class StopState extends ElevatorState {
public StopState(Elevator elevator) {
super(elevator);
}
@Override
public void openDoor() {
System.out.println("电梯门打开");
elevator.setState(elevator.getOpenState());
}
@Override
public void closeDoor() {
System.out.println("电梯门关闭");
elevator.setState(elevator.getCloseState());
}
@Override
public void run() {
System.out.println("电梯开始运行");
elevator.setState(elevator.getRunState());
}
@Override
public void stop() {
System.out.println("电梯已经停止");
}
}
// ============== 上下文类 ==============
class Elevator {
private ElevatorState openState;
private ElevatorState closeState;
private ElevatorState runState;
private ElevatorState stopState;
private ElevatorState currentState;
public Elevator() {
openState = new OpenState(this);
closeState = new CloseState(this);
runState = new RunState(this);
stopState = new StopState(this);
// 初始状态为停止状态
currentState = stopState;
}
public void setState(ElevatorState state) {
this.currentState = state;
}
// 对外提供的方法
public void openDoor() {
currentState.openDoor();
}
public void closeDoor() {
currentState.closeDoor();
}
public void run() {
currentState.run();
}
public void stop() {
currentState.stop();
}
// Getter方法
public ElevatorState getOpenState() {
return openState;
}
public ElevatorState getCloseState() {
return closeState;
}
public ElevatorState getRunState() {
return runState;
}
public ElevatorState getStopState() {
return stopState;
}
}
// ============== 测试类 ==============
public class StateTest {
public static void main(String[] args) {
Elevator elevator = new Elevator();
System.out.println("=== 初始状态:停止 ===");
elevator.openDoor();
elevator.closeDoor();
elevator.run();
elevator.stop();
System.out.println("\n=== 运行状态 ===");
elevator.openDoor();
elevator.closeDoor();
elevator.stop();
}
}
C# 经典实现
// ============== 抽象状态类 ==============
public abstract class ElevatorState
{
protected Elevator _elevator;
public ElevatorState(Elevator elevator)
{
_elevator = elevator;
}
public abstract void OpenDoor();
public abstract void CloseDoor();
public abstract void Run();
public abstract void Stop();
}
// ============== 具体状态类 ==============
public class OpenState : ElevatorState
{
public OpenState(Elevator elevator) : base(elevator) { }
public override void OpenDoor()
{
Console.WriteLine("电梯门已经是打开状态");
}
public override void CloseDoor()
{
Console.WriteLine("电梯门关闭");
_elevator.SetState(_elevator.GetCloseState());
}
public override void Run()
{
Console.WriteLine("电梯门打开,不能运行");
}
public override void Stop()
{
Console.WriteLine("电梯已经停止");
}
}
public class CloseState : ElevatorState
{
public CloseState(Elevator elevator) : base(elevator) { }
public override void OpenDoor()
{
Console.WriteLine("电梯门打开");
_elevator.SetState(_elevator.GetOpenState());
}
public override void CloseDoor()
{
Console.WriteLine("电梯门已经是关闭状态");
}
public override void Run()
{
Console.WriteLine("电梯开始运行");
_elevator.SetState(_elevator.GetRunState());
}
public override void Stop()
{
Console.WriteLine("电梯已经停止");
}
}
public class RunState : ElevatorState
{
public RunState(Elevator elevator) : base(elevator) { }
public override void OpenDoor()
{
Console.WriteLine("电梯正在运行,不能开门");
}
public override void CloseDoor()
{
Console.WriteLine("电梯门已经关闭");
}
public override void Run()
{
Console.WriteLine("电梯正在运行");
}
public override void Stop()
{
Console.WriteLine("电梯停止运行");
_elevator.SetState(_elevator.GetStopState());
}
}
public class StopState : ElevatorState
{
public StopState(Elevator elevator) : base(elevator) { }
public override void OpenDoor()
{
Console.WriteLine("电梯门打开");
_elevator.SetState(_elevator.GetOpenState());
}
public override void CloseDoor()
{
Console.WriteLine("电梯门关闭");
_elevator.SetState(_elevator.GetCloseState());
}
public override void Run()
{
Console.WriteLine("电梯开始运行");
_elevator.SetState(_elevator.GetRunState());
}
public override void Stop()
{
Console.WriteLine("电梯已经停止");
}
}
// ============== 上下文类 ==============
public class Elevator
{
private ElevatorState _openState;
private ElevatorState _closeState;
private ElevatorState _runState;
private ElevatorState _stopState;
private ElevatorState _currentState;
public Elevator()
{
_openState = new OpenState(this);
_closeState = new CloseState(this);
_runState = new RunState(this);
_stopState = new StopState(this);
// 初始状态为停止状态
_currentState = _stopState;
}
public void SetState(ElevatorState state)
{
_currentState = state;
}
// 对外提供的方法
public void OpenDoor()
{
_currentState.OpenDoor();
}
public void CloseDoor()
{
_currentState.CloseDoor();
}
public void Run()
{
_currentState.Run();
}
public void Stop()
{
_currentState.Stop();
}
// Getter方法
public ElevatorState GetOpenState()
{
return _openState;
}
public ElevatorState GetCloseState()
{
return _closeState;
}
public ElevatorState GetRunState()
{
return _runState;
}
public ElevatorState GetStopState()
{
return _stopState;
}
}
// ============== 测试类 ==============
public class StateTest
{
public static void Main()
{
Elevator elevator = new Elevator();
Console.WriteLine("=== 初始状态:停止 ===");
elevator.OpenDoor();
elevator.CloseDoor();
elevator.Run();
elevator.Stop();
Console.WriteLine("\n=== 运行状态 ===");
elevator.OpenDoor();
elevator.CloseDoor();
elevator.Stop();
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象状态类 ==============
class ElevatorState(ABC):
def __init__(self, elevator):
self._elevator = elevator
@abstractmethod
def open_door(self):
pass
@abstractmethod
def close_door(self):
pass
@abstractmethod
def run(self):
pass
@abstractmethod
def stop(self):
pass
# ============== 具体状态类 ==============
class OpenState(ElevatorState):
def open_door(self):
print("电梯门已经是打开状态")
def close_door(self):
print("电梯门关闭")
self._elevator.set_state(self._elevator.get_close_state())
def run(self):
print("电梯门打开,不能运行")
def stop(self):
print("电梯已经停止")
class CloseState(ElevatorState):
def open_door(self):
print("电梯门打开")
self._elevator.set_state(self._elevator.get_open_state())
def close_door(self):
print("电梯门已经是关闭状态")
def run(self):
print("电梯开始运行")
self._elevator.set_state(self._elevator.get_run_state())
def stop(self):
print("电梯已经停止")
class RunState(ElevatorState):
def open_door(self):
print("电梯正在运行,不能开门")
def close_door(self):
print("电梯门已经关闭")
def run(self):
print("电梯正在运行")
def stop(self):
print("电梯停止运行")
self._elevator.set_state(self._elevator.get_stop_state())
class StopState(ElevatorState):
def open_door(self):
print("电梯门打开")
self._elevator.set_state(self._elevator.get_open_state())
def close_door(self):
print("电梯门关闭")
self._elevator.set_state(self._elevator.get_close_state())
def run(self):
print("电梯开始运行")
self._elevator.set_state(self._elevator.get_run_state())
def stop(self):
print("电梯已经停止")
# ============== 上下文类 ==============
class Elevator:
def __init__(self):
self._open_state = OpenState(self)
self._close_state = CloseState(self)
self._run_state = RunState(self)
self._stop_state = StopState(self)
# 初始状态为停止状态
self._current_state = self._stop_state
def set_state(self, state):
self._current_state = state
# 对外提供的方法
def open_door(self):
self._current_state.open_door()
def close_door(self):
self._current_state.close_door()
def run(self):
self._current_state.run()
def stop(self):
self._current_state.stop()
# Getter方法
def get_open_state(self):
return self._open_state
def get_close_state(self):
return self._close_state
def get_run_state(self):
return self._run_state
def get_stop_state(self):
return self._stop_state
# ============== 测试代码 ==============
if __name__ == "__main__":
elevator = Elevator()
print("=== 初始状态:停止 ===")
elevator.open_door()
elevator.close_door()
elevator.run()
elevator.stop()
print("\n=== 运行状态 ===")
elevator.open_door()
elevator.close_door()
elevator.stop()
🏗️ 架构级应用
把状态模式的思想从"对象状态管理"放大到"系统状态管理",就变成了架构层面的状态机/工作流引擎。
-
有限状态机(FSM):用于管理系统的状态和状态之间的转换
-
工作流引擎:用于管理业务流程的状态和流转
-
订单状态管理:电商平台的订单状态流转
-
支付状态管理:支付系统的支付状态流转
🏭 工业级中间件案例
-
Spring Statemachine:Spring提供的状态机框架
-
Activiti/Camunda:工作流引擎,基于状态机实现
-
电商订单系统:几乎所有电商平台的订单系统都使用状态模式
-
支付系统:支付宝、微信支付的支付状态管理
-
游戏开发:游戏中的角色状态、场景状态管理
⚠️ 实战优化避坑(三语完整实现)
坑点1:状态类过多问题
问题:系统状态太多,导致状态类数量爆炸
解决方案:
-
使用枚举状态代替类状态
-
使用状态表代替状态类
// 枚举状态简化实现
public enum ElevatorState {
OPEN {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯门已经是打开状态");
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯门关闭");
elevator.setState(CLOSE);
}
@Override
public void run(Elevator elevator) {
System.out.println("电梯门打开,不能运行");
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯已经停止");
}
},
CLOSE {
// 实现方法...
},
RUN {
// 实现方法...
},
STOP {
// 实现方法...
};
public abstract void openDoor(Elevator elevator);
public abstract void closeDoor(Elevator elevator);
public abstract void run(Elevator elevator);
public abstract void stop(Elevator elevator);
}
坑点2:与策略模式混淆
问题:状态模式和策略模式结构非常相似,容易混淆
解决方案:
-
状态模式:状态驱动行为,对象的行为由它的状态决定,状态会自动转换
-
策略模式:用户选择算法,对象的行为由用户选择的策略决定,策略需要手动切换
坑点3:状态转换复杂问题
问题:状态之间的转换关系复杂,难以维护
解决方案:
-
使用状态图清晰地表示状态之间的转换关系
-
使用状态机框架(如Spring Statemachine)管理状态转换
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:抽象状态类、具体状态类、上下文类 |
| 架构级 | 有限状态机、工作流引擎、订单状态管理、支付状态管理 |
| 工业级 | Spring Statemachine、Activiti/Camunda、电商订单系统、支付系统 |
第二阶8个设计模式速查表
| 模式名称 | 类别 | 核心一句话 | 生活场景 | 工业级案例 |
|---|---|---|---|---|
| 代理模式 | 结构型 | 为其他对象提供代理以控制访问 | 房产中介、明星经纪人 | Spring AOP、Dubbo、Nginx反向代理 |
| 外观模式 | 结构型 | 为复杂子系统提供统一入口 | 医院导诊台、政务大厅总窗口 | Spring Cloud Gateway、云服务SDK |
| 模板方法模式 | 行为型 | 定义算法骨架,子类实现特定步骤 | 泡饮品、作文格式 | Spring MVC、MyBatis、JUnit |
| 适配器模式 | 结构型 | 转换接口,解决不兼容问题 | 转换插头、翻译官 | JDBC、SLF4J、消息队列适配器 |
| 建造者模式 | 创建型 | 构建复杂对象,分离构建与表示 | 定制汉堡、组装电脑 | StringBuilder、SQL构建器、Lombok @Builder |
| 责任链模式 | 行为型 | 请求沿链传递,直到被处理 | 公司请假审批、公文流转 | Servlet Filter、Spring Interceptor、Netty |
| 命令模式 | 行为型 | 封装请求为对象,支持撤销/排队 | 餐厅点餐、遥控器按钮 | 消息队列、定时任务框架、编辑器撤销 |
| 状态模式 | 行为型 | 状态改变时改变行为,消灭if-else | 电梯状态、订单状态 | Spring Statemachine、工作流引擎、电商订单系统 |
第14章 抽象工厂模式(Abstract Factory)- 创建型
核心一句话:提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类
🏠 生活真实故事
你要装修一套房子,需要购买一整套家具:
-
客厅需要沙发、茶几、电视柜
-
卧室需要床、衣柜、床头柜
-
餐厅需要餐桌、餐椅
市场上有不同风格的家具:
-
现代简约风格
-
中式古典风格
-
欧式奢华风格
如果你单独购买每件家具,很容易出现风格不统一的问题。
于是你找了家具品牌店:
-
每个品牌店只卖一种风格的家具
-
你选择一个品牌,就能买到一整套风格统一的家具
-
不需要担心沙发和茶几风格不搭配的问题
📚 文科类比
-
汽车品牌4S店:每个品牌4S店只卖自己品牌的汽车、配件和提供售后服务
-
服装品牌店:每个品牌店只卖自己品牌的上衣、裤子、鞋子和配饰
-
出版社:每个出版社出版自己系列的书籍、杂志和音像制品
-
餐厅套餐:每个套餐包含主食、配菜、汤和饮料,都是搭配好的
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象产品 ==============
// 【核心1】抽象产品族:定义一组相关产品的接口
// 抽象工厂创建的是一组产品,而非单一产品
interface Sofa {
void sit();
}
interface CoffeeTable {
void putThings();
}
interface TVStand {
void placeTV();
}
// ============== 具体产品:现代风格 ==============
// 【核心2】具体产品:实现抽象产品接口
// 同一风格的产品组成一个产品族
class ModernSofa implements Sofa {
@Override
public void sit() {
System.out.println("坐在现代简约沙发上");
}
}
class ModernCoffeeTable implements CoffeeTable {
@Override
public void putThings() {
System.out.println("在现代简约茶几上放东西");
}
}
class ModernTVStand implements TVStand {
@Override
public void placeTV() {
System.out.println("在现代简约电视柜上放电视");
}
}
// ============== 具体产品:中式风格 ==============
// 另一个产品族:中式风格
class ChineseSofa implements Sofa {
@Override
public void sit() {
System.out.println("坐在中式古典沙发上");
}
}
class ChineseCoffeeTable implements CoffeeTable {
@Override
public void putThings() {
System.out.println("在中式古典茶几上放东西");
}
}
class ChineseTVStand implements TVStand {
@Override
public void placeTV() {
System.out.println("在中式古典电视柜上放电视");
}
}
// ============== 抽象工厂 ==============
// 【核心3】抽象工厂:声明创建一组产品的方法
// 每个方法对应一个产品类型
interface FurnitureFactory {
Sofa createSofa();
CoffeeTable createCoffeeTable();
TVStand createTVStand();
}
// ============== 具体工厂 ==============
// 【核心4】具体工厂:实现创建一组产品的方法
// 每个具体工厂负责创建一个完整的产品族
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ModernSofa(); // 创建现代风格沙发
}
@Override
public CoffeeTable createCoffeeTable() {
return new ModernCoffeeTable(); // 创建现代风格茶几
}
@Override
public TVStand createTVStand() {
return new ModernTVStand(); // 创建现代风格电视柜
}
}
class ChineseFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ChineseSofa(); // 创建中式风格沙发
}
@Override
public CoffeeTable createCoffeeTable() {
return new ChineseCoffeeTable();
}
@Override
public TVStand createTVStand() {
return new ChineseTVStand();
}
}
// ============== 测试类 ==============
public class AbstractFactoryTest {
public static void main(String[] args) {
// 【优势】切换产品族只需更换工厂,无需修改客户端代码
// 使用现代风格家具
FurnitureFactory modernFactory = new ModernFurnitureFactory();
Sofa modernSofa = modernFactory.createSofa();
CoffeeTable modernTable = modernFactory.createCoffeeTable();
TVStand modernStand = modernFactory.createTVStand();
modernSofa.sit();
modernTable.putThings();
modernStand.placeTV();
System.out.println();
// 使用中式风格家具
FurnitureFactory chineseFactory = new ChineseFurnitureFactory();
Sofa chineseSofa = chineseFactory.createSofa();
CoffeeTable chineseTable = chineseFactory.createCoffeeTable();
TVStand chineseStand = chineseFactory.createTVStand();
chineseSofa.sit();
chineseTable.putThings();
chineseStand.placeTV();
}
}
C# 经典实现
// ============== 抽象产品 ==============
// 【核心1】抽象产品族:定义一组相关产品的接口
public interface ISofa
{
void Sit();
}
public interface ICoffeeTable
{
void PutThings();
}
public interface ITVStand
{
void PlaceTV();
}
// ============== 具体产品:现代风格 ==============
// 【核心2】具体产品:实现抽象产品接口,同一风格组成产品族
public class ModernSofa : ISofa
{
public void Sit()
{
Console.WriteLine("坐在现代简约沙发上");
}
}
public class ModernCoffeeTable : ICoffeeTable
{
public void PutThings()
{
Console.WriteLine("在现代简约茶几上放东西");
}
}
public class ModernTVStand : ITVStand
{
public void PlaceTV()
{
Console.WriteLine("在现代简约电视柜上放电视");
}
}
// ============== 具体产品:中式风格 ==============
// 另一个产品族:中式风格
public class ChineseSofa : ISofa
{
public void Sit()
{
Console.WriteLine("坐在中式古典沙发上");
}
}
public class ChineseCoffeeTable : ICoffeeTable
{
public void PutThings()
{
Console.WriteLine("在中式古典茶几上放东西");
}
}
public class ChineseTVStand : ITVStand
{
public void PlaceTV()
{
Console.WriteLine("在中式古典电视柜上放电视");
}
}
// ============== 抽象工厂 ==============
// 【核心3】抽象工厂:声明创建一组产品的方法
public interface IFurnitureFactory
{
ISofa CreateSofa();
ICoffeeTable CreateCoffeeTable();
ITVStand CreateTVStand();
}
// ============== 具体工厂 ==============
// 【核心4】具体工厂:每个工厂创建一个完整的产品族
public class ModernFurnitureFactory : IFurnitureFactory
{
public ISofa CreateSofa()
{
return new ModernSofa();
}
public ICoffeeTable CreateCoffeeTable()
{
return new ModernCoffeeTable();
}
public ITVStand CreateTVStand()
{
return new ModernTVStand();
}
}
public class ChineseFurnitureFactory : IFurnitureFactory
{
public ISofa CreateSofa()
{
return new ChineseSofa();
}
public ICoffeeTable CreateCoffeeTable()
{
return new ChineseCoffeeTable();
}
public ITVStand CreateTVStand()
{
return new ChineseTVStand();
}
}
// ============== 测试类 ==============
public class AbstractFactoryTest
{
public static void Main()
{
// 【优势】切换产品族只需更换工厂
// 使用现代风格家具
IFurnitureFactory modernFactory = new ModernFurnitureFactory();
ISofa modernSofa = modernFactory.CreateSofa();
ICoffeeTable modernTable = modernFactory.CreateCoffeeTable();
ITVStand modernStand = modernFactory.CreateTVStand();
modernSofa.Sit();
modernTable.PutThings();
modernStand.PlaceTV();
Console.WriteLine();
// 使用中式风格家具
IFurnitureFactory chineseFactory = new ChineseFurnitureFactory();
ISofa chineseSofa = chineseFactory.CreateSofa();
ICoffeeTable chineseTable = chineseFactory.CreateCoffeeTable();
ITVStand chineseStand = chineseFactory.CreateTVStand();
chineseSofa.Sit();
chineseTable.PutThings();
chineseStand.PlaceTV();
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象产品 ==============
# 【核心1】抽象产品族:定义一组相关产品的接口
class Sofa(ABC):
@abstractmethod
def sit(self):
pass
class CoffeeTable(ABC):
@abstractmethod
def put_things(self):
pass
class TVStand(ABC):
@abstractmethod
def place_tv(self):
pass
# ============== 具体产品:现代风格 ==============
# 【核心2】具体产品:同一风格的产品组成产品族
class ModernSofa(Sofa):
def sit(self):
print("坐在现代简约沙发上")
class ModernCoffeeTable(CoffeeTable):
def put_things(self):
print("在现代简约茶几上放东西")
class ModernTVStand(TVStand):
def place_tv(self):
print("在现代简约电视柜上放电视")
# ============== 具体产品:中式风格 ==============
# 另一个产品族
class ChineseSofa(Sofa):
def sit(self):
print("坐在中式古典沙发上")
class ChineseCoffeeTable(CoffeeTable):
def put_things(self):
print("在中式古典茶几上放东西")
class ChineseTVStand(TVStand):
def place_tv(self):
print("在中式古典电视柜上放电视")
# ============== 抽象工厂 ==============
# 【核心3】抽象工厂:声明创建一组产品的方法
class FurnitureFactory(ABC):
@abstractmethod
def create_sofa(self):
pass
@abstractmethod
def create_coffee_table(self):
pass
@abstractmethod
def create_tv_stand(self):
pass
# ============== 具体工厂 ==============
# 【核心4】具体工厂:每个工厂创建一个完整的产品族
class ModernFurnitureFactory(FurnitureFactory):
def create_sofa(self):
return ModernSofa()
def create_coffee_table(self):
return ModernCoffeeTable()
def create_tv_stand(self):
return ModernTVStand()
class ChineseFurnitureFactory(FurnitureFactory):
def create_sofa(self):
return ChineseSofa()
def create_coffee_table(self):
return ChineseCoffeeTable()
def create_tv_stand(self):
return ChineseTVStand()
# ============== 测试代码 ==============
if __name__ == "__main__":
# 【优势】切换产品族只需更换工厂
# 使用现代风格家具
modern_factory = ModernFurnitureFactory()
modern_sofa = modern_factory.create_sofa()
modern_table = modern_factory.create_coffee_table()
modern_stand = modern_factory.create_tv_stand()
modern_sofa.sit()
modern_table.put_things()
modern_stand.place_tv()
print()
# 使用中式风格家具
chinese_factory = ChineseFurnitureFactory()
chinese_sofa = chinese_factory.create_sofa()
chinese_table = chinese_factory.create_coffee_table()
chinese_stand = chinese_factory.create_tv_stand()
chinese_sofa.sit()
chinese_table.put_things()
chinese_stand.place_tv()
🏗️ 架构级应用
把抽象工厂模式的思想从"创建一组相关对象"放大到"创建一组相关服务",就变成了架构层面的服务族工厂。
-
跨平台UI组件库:为不同操作系统(Windows、macOS、Linux)创建风格统一的UI组件
-
数据库访问层:为不同数据库(MySQL、Oracle、PostgreSQL)创建统一的数据访问接口
-
消息队列适配器:为不同消息队列(RocketMQ、Kafka、RabbitMQ)创建统一的消息发送和接收接口
-
云服务SDK:为不同云服务商(阿里云、腾讯云、AWS)创建统一的云服务接口
🏭 工业级中间件案例
-
Java AWT/Swing:为不同操作系统提供统一的UI组件接口
-
MyBatis SqlSessionFactory:创建不同类型的SqlSession对象
-
Spring BeanFactory:创建不同类型的Bean对象
-
Hibernate SessionFactory:创建不同类型的Session对象
-
JDBC DriverManager:为不同数据库创建统一的Connection对象
⚠️ 实战优化避坑(三语完整实现)
坑点1:产品族扩展困难
问题:如果需要在产品族中添加一个新的产品类型,需要修改所有的工厂类
解决方案:使用抽象工厂模式时,要提前规划好产品族的结构,尽量避免后期添加新的产品类型
坑点2:与工厂方法模式混淆
问题:抽象工厂模式和工厂方法模式都是创建型模式,容易混淆
解决方案:
-
工厂方法模式:创建单一产品,一个工厂只创建一种产品
-
抽象工厂模式:创建一组相关产品,一个工厂创建多种相关产品
坑点3:工厂类过多问题
问题:产品族太多会导致工厂类数量爆炸
解决方案:使用简单工厂模式结合配置文件,动态创建工厂对象
// 使用配置文件动态创建工厂
public class FurnitureFactoryConfig {
private static Properties props = new Properties();
static {
try {
props.load(FurnitureFactoryConfig.class.getClassLoader().getResourceAsStream("factory.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static FurnitureFactory getFactory() {
String factoryClass = props.getProperty("furniture.factory");
try {
return (FurnitureFactory) Class.forName(factoryClass).newInstance();
} catch (Exception e) {
e.printStackTrace();
return new ModernFurnitureFactory();
}
}
}
// 使用
public class AbstractFactoryTest {
public static void main(String[] args) {
FurnitureFactory factory = FurnitureFactoryConfig.getFactory();
Sofa sofa = factory.createSofa();
sofa.sit();
}
}
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心四要素:抽象产品、具体产品、抽象工厂、具体工厂 |
| 架构级 | 跨平台UI组件库、数据库访问层、消息队列适配器、云服务SDK |
| 工业级 | Java AWT/Swing、MyBatis SqlSessionFactory、Spring BeanFactory、JDBC DriverManager |
第15章 组合模式(Composite)- 结构型
核心一句话:将对象组合成树形结构以表示"部分-整体"的层次关系。组合模式使得用户可以统一处理单个对象和组合对象
🏠 生活真实故事
你电脑上的文件系统:
-
有文件(File),也有文件夹(Folder)
-
文件夹里可以包含文件,也可以包含子文件夹
-
你可以对文件执行"打开"、“删除”、"复制"等操作
-
你也可以对文件夹执行"打开"、“删除”、"复制"等操作
你不需要区分当前操作的是文件还是文件夹,它们的操作方式是一样的。
📚 文科类比
-
公司组织架构:公司有部门和员工,部门里可以包含子部门和员工
-
菜单导航:菜单有菜单项和子菜单,子菜单里可以包含菜单项和子菜单
-
书籍目录:书籍有章节和小节,章节里可以包含小节和子章节
-
地理划分:国家有省和市,省里可以包含市和县
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象组件 ==============
// 【核心1】抽象组件:定义叶子节点和组合节点的统一接口
// 客户端可以统一处理单个对象和组合对象
abstract class FileSystemComponent {
protected String name;
public FileSystemComponent(String name) {
this.name = name;
}
public abstract void display(int depth);
// 【透明模式】在抽象类中定义子节点管理方法
// 叶子节点不需要这些方法,默认抛出异常
public void add(FileSystemComponent component) {
throw new UnsupportedOperationException();
}
public void remove(FileSystemComponent component) {
throw new UnsupportedOperationException();
}
public FileSystemComponent getChild(int index) {
throw new UnsupportedOperationException();
}
}
// ============== 叶子节点:文件 ==============
// 【核心2】叶子节点:没有子节点的基本对象
class File extends FileSystemComponent {
public File(String name) {
super(name);
}
@Override
public void display(int depth) {
// 叶子节点只显示自己
System.out.println("-".repeat(depth) + " 文件:" + name);
}
}
// ============== 组合节点:文件夹 ==============
// 【核心3】组合节点:包含子节点的容器对象
// 组合节点可以包含叶子节点,也可以包含其他组合节点(递归结构)
class Folder extends FileSystemComponent {
// 存储子组件列表(可以是File或Folder)
private List<FileSystemComponent> children = new ArrayList<>();
public Folder(String name) {
super(name);
}
@Override
public void add(FileSystemComponent component) {
children.add(component);
}
@Override
public void remove(FileSystemComponent component) {
children.remove(component);
}
@Override
public FileSystemComponent getChild(int index) {
return children.get(index);
}
@Override
public void display(int depth) {
// 先显示自己
System.out.println("-".repeat(depth) + " 文件夹:" + name);
// 【关键】递归调用所有子组件的display方法
// 无论是叶子还是组合节点,都统一调用display
for (FileSystemComponent component : children) {
component.display(depth + 2);
}
}
}
// ============== 测试类 ==============
public class CompositeTest {
public static void main(String[] args) {
// 创建根文件夹(组合节点)
Folder root = new Folder("我的电脑");
// 创建子文件夹(组合节点)
Folder documents = new Folder("我的文档");
Folder pictures = new Folder("我的图片");
// 创建文件(叶子节点)
File resume = new File("简历.docx");
File photo1 = new File("风景.jpg");
File photo2 = new File("家人.jpg");
// 组合树形结构
root.add(documents);
root.add(pictures);
documents.add(resume);
pictures.add(photo1);
pictures.add(photo2);
// 【优势】统一调用display,无需区分文件和文件夹
// 组合模式自动处理递归遍历
root.display(0);
}
}
C# 经典实现
// ============== 抽象组件 ==============
// 【核心1】抽象组件:定义叶子节点和组合节点的统一接口
public abstract class FileSystemComponent
{
protected string _name;
public FileSystemComponent(string name)
{
_name = name;
}
public abstract void Display(int depth);
// 【透明模式】在抽象类中定义子节点管理方法
// 叶子节点不需要这些方法,默认抛出异常
public virtual void Add(FileSystemComponent component)
{
throw new NotImplementedException();
}
public virtual void Remove(FileSystemComponent component)
{
throw new NotImplementedException();
}
public virtual FileSystemComponent GetChild(int index)
{
throw new NotImplementedException();
}
}
// ============== 叶子节点:文件 ==============
// 【核心2】叶子节点:没有子节点的基本对象
public class File : FileSystemComponent
{
public File(string name) : base(name) { }
public override void Display(int depth)
{
// 叶子节点只显示自己
Console.WriteLine(new string('-', depth) + " 文件:" + _name);
}
}
// ============== 组合节点:文件夹 ==============
// 【核心3】组合节点:包含子节点的容器对象
// 可以包含叶子节点,也可以包含其他组合节点(递归结构)
public class Folder : FileSystemComponent
{
// 存储子组件列表(可以是File或Folder)
private List<FileSystemComponent> _children = new List<FileSystemComponent>();
public Folder(string name) : base(name) { }
public override void Add(FileSystemComponent component)
{
_children.Add(component);
}
public override void Remove(FileSystemComponent component)
{
_children.Remove(component);
}
public override FileSystemComponent GetChild(int index)
{
return _children[index];
}
public override void Display(int depth)
{
// 先显示自己
Console.WriteLine(new string('-', depth) + " 文件夹:" + _name);
// 【关键】递归调用所有子组件的Display方法
foreach (FileSystemComponent component in _children)
{
component.Display(depth + 2);
}
}
}
// ============== 测试类 ==============
public class CompositeTest
{
public static void Main()
{
// 创建根文件夹(组合节点)
Folder root = new Folder("我的电脑");
// 创建子文件夹(组合节点)
Folder documents = new Folder("我的文档");
Folder pictures = new Folder("我的图片");
// 创建文件(叶子节点)
File resume = new File("简历.docx");
File photo1 = new File("风景.jpg");
File photo2 = new File("家人.jpg");
// 组合树形结构
root.Add(documents);
root.Add(pictures);
documents.Add(resume);
pictures.Add(photo1);
pictures.Add(photo2);
// 【优势】统一调用Display,无需区分文件和文件夹
root.Display(0);
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象组件 ==============
class FileSystemComponent(ABC):
def __init__(self, name):
self.name = name
@abstractmethod
def display(self, depth):
pass
def add(self, component):
raise NotImplementedError()
def remove(self, component):
raise NotImplementedError()
def get_child(self, index):
raise NotImplementedError()
# ============== 叶子节点:文件 ==============
class File(FileSystemComponent):
def display(self, depth):
print("-" * depth + " 文件:" + self.name)
# ============== 组合节点:文件夹 ==============
class Folder(FileSystemComponent):
def __init__(self, name):
super().__init__(name)
self.children = []
def add(self, component):
self.children.append(component)
def remove(self, component):
self.children.remove(component)
def get_child(self, index):
return self.children[index]
def display(self, depth):
print("-" * depth + " 文件夹:" + self.name)
for component in self.children:
component.display(depth + 2)
# ============== 测试代码 ==============
if __name__ == "__main__":
# 创建根文件夹
root = Folder("我的电脑")
# 创建子文件夹
documents = Folder("我的文档")
pictures = Folder("我的图片")
# 创建文件
resume = File("简历.docx")
photo1 = File("风景.jpg")
photo2 = File("家人.jpg")
# 组合树形结构
root.add(documents)
root.add(pictures)
documents.add(resume)
pictures.add(photo1)
pictures.add(photo2)
# 显示整个文件系统
root.display(0)
🏗️ 架构级应用
把组合模式的思想从"文件系统"放大到"系统架构",就变成了架构层面的树形结构处理。
-
XML/JSON解析:将XML/JSON文档解析成树形结构,统一处理节点和元素
-
GUI组件库:将UI组件组织成树形结构,统一处理容器和控件
-
权限管理系统:将权限组织成树形结构,统一处理权限和权限组
-
工作流引擎:将工作流节点组织成树形结构,统一处理节点和子流程
🏭 工业级中间件案例
-
Java Swing/AWT:所有UI组件都继承自Component,容器可以包含其他组件
-
Android View系统:所有View都继承自View,ViewGroup可以包含其他View
-
HTML DOM:将HTML文档解析成树形结构,统一处理元素和节点
-
JDOM/DOM4J:XML解析库,将XML文档解析成树形结构
-
Jackson/Gson:JSON解析库,将JSON文档解析成树形结构
⚠️ 实战优化避坑(三语完整实现)
坑点1:透明模式与安全模式的选择
问题:组合模式有两种实现方式:透明模式和安全模式
解决方案:
-
透明模式:叶子节点和组合节点实现相同的接口,客户端可以统一处理,但叶子节点的add/remove方法会抛出异常
-
安全模式:叶子节点和组合节点实现不同的接口,客户端需要区分处理,但更安全
坑点2:递归深度问题
问题:树形结构过深会导致递归调用栈溢出
解决方案:使用迭代方式代替递归方式遍历树形结构
// 迭代方式遍历树形结构
public void displayIterative() {
Stack<Pair<FileSystemComponent, Integer>> stack = new Stack<>();
stack.push(new Pair<>(this, 0));
while (!stack.isEmpty()) {
Pair<FileSystemComponent, Integer> pair = stack.pop();
FileSystemComponent component = pair.getKey();
int depth = pair.getValue();
if (component instanceof Folder) {
System.out.println("-".repeat(depth) + " 文件夹:" + component.name);
// 逆序入栈,保证顺序正确
List<FileSystemComponent> children = ((Folder) component).children;
for (int i = children.size() - 1; i >= 0; i--) {
stack.push(new Pair<>(children.get(i), depth + 2));
}
} else {
System.out.println("-".repeat(depth) + " 文件:" + component.name);
}
}
}
坑点3:循环引用问题
问题:如果组合节点包含自己,会导致无限递归
解决方案:在添加子节点时检查是否会形成循环引用
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心三要素:抽象组件、叶子节点、组合节点 |
| 架构级 | XML/JSON解析、GUI组件库、权限管理系统、工作流引擎 |
| 工业级 | Java Swing/AWT、Android View系统、HTML DOM、JDOM/DOM4J |
第16章 迭代器模式(Iterator)- 行为型
核心一句话:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示
🏠 生活真实故事
你去图书馆借书:
-
图书馆有很多书架,每个书架上有很多书
-
你不需要知道书是怎么放在书架上的,也不需要知道书架是怎么排列的
-
你只需要拿着借书证,告诉图书管理员你要借什么书
-
图书管理员会帮你找到书并交给你
在这里,图书管理员就是一个迭代器:
-
他知道如何遍历图书馆的所有书架
-
他知道如何在书架上找到你要的书
-
你不需要了解图书馆的内部结构,只需要和图书管理员打交道
📚 文科类比
-
导游:导游带领游客参观景点,游客不需要知道景点的具体位置和路线
-
快递员:快递员将包裹送到你手中,你不需要知道包裹是怎么运输的
-
餐厅服务员:服务员将菜从厨房送到你桌上,你不需要知道厨房的内部结构
-
电视遥控器:你通过遥控器切换电视频道,不需要知道电视内部是怎么工作的
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 迭代器接口 ==============
interface Iterator<T> {
boolean hasNext();
T next();
}
// ============== 聚合接口 ==============
interface Aggregate<T> {
Iterator<T> createIterator();
}
// ============== 具体聚合:书架 ==============
class BookShelf implements Aggregate<Book> {
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
public Book getBook(int index) {
return books.get(index);
}
public int getSize() {
return books.size();
}
@Override
public Iterator<Book> createIterator() {
return new BookShelfIterator(this);
}
}
// ============== 具体迭代器:书架迭代器 ==============
class BookShelfIterator implements Iterator<Book> {
private BookShelf bookShelf;
private int index = 0;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return index < bookShelf.getSize();
}
@Override
public Book next() {
Book book = bookShelf.getBook(index);
index++;
return book;
}
}
// ============== 实体类:书 ==============
class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// ============== 测试类 ==============
public class IteratorTest {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
bookShelf.addBook(new Book("设计模式"));
bookShelf.addBook(new Book("Java编程思想"));
bookShelf.addBook(new Book("深入理解Java虚拟机"));
Iterator<Book> iterator = bookShelf.createIterator();
while (iterator.hasNext()) {
Book book = iterator.next();
System.out.println("书名:" + book.getName());
}
}
}
C# 经典实现
// ============== 迭代器接口 ==============
public interface IIterator<T>
{
bool HasNext();
T Next();
}
// ============== 聚合接口 ==============
public interface IAggregate<T>
{
IIterator<T> CreateIterator();
}
// ============== 具体聚合:书架 ==============
public class BookShelf : IAggregate<Book>
{
private List<Book> _books = new List<Book>();
public void AddBook(Book book)
{
_books.Add(book);
}
public Book GetBook(int index)
{
return _books[index];
}
public int GetSize()
{
return _books.Count;
}
public IIterator<Book> CreateIterator()
{
return new BookShelfIterator(this);
}
}
// ============== 具体迭代器:书架迭代器 ==============
public class BookShelfIterator : IIterator<Book>
{
private BookShelf _bookShelf;
private int _index = 0;
public BookShelfIterator(BookShelf bookShelf)
{
_bookShelf = bookShelf;
}
public bool HasNext()
{
return _index < _bookShelf.GetSize();
}
public Book Next()
{
Book book = _bookShelf.GetBook(_index);
_index++;
return book;
}
}
// ============== 实体类:书 ==============
public class Book
{
public string Name { get; set; }
public Book(string name)
{
Name = name;
}
}
// ============== 测试类 ==============
public class IteratorTest
{
public static void Main()
{
BookShelf bookShelf = new BookShelf();
bookShelf.AddBook(new Book("设计模式"));
bookShelf.AddBook(new Book("C#编程思想"));
bookShelf.AddBook(new Book("深入理解C#"));
IIterator<Book> iterator = bookShelf.CreateIterator();
while (iterator.HasNext())
{
Book book = iterator.Next();
Console.WriteLine("书名:" + book.Name);
}
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 迭代器接口 ==============
class Iterator(ABC):
@abstractmethod
def has_next(self):
pass
@abstractmethod
def next(self):
pass
# ============== 聚合接口 ==============
class Aggregate(ABC):
@abstractmethod
def create_iterator(self):
pass
# ============== 具体聚合:书架 ==============
class BookShelf(Aggregate):
def __init__(self):
self.books = []
def add_book(self, book):
self.books.append(book)
def get_book(self, index):
return self.books[index]
def get_size(self):
return len(self.books)
def create_iterator(self):
return BookShelfIterator(self)
# ============== 具体迭代器:书架迭代器 ==============
class BookShelfIterator(Iterator):
def __init__(self, book_shelf):
self.book_shelf = book_shelf
self.index = 0
def has_next(self):
return self.index < self.book_shelf.get_size()
def next(self):
book = self.book_shelf.get_book(self.index)
self.index += 1
return book
# ============== 实体类:书 ==============
class Book:
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
# ============== 测试代码 ==============
if __name__ == "__main__":
book_shelf = BookShelf()
book_shelf.add_book(Book("设计模式"))
book_shelf.add_book(Book("Python编程思想"))
book_shelf.add_book(Book("流畅的Python"))
iterator = book_shelf.create_iterator()
while iterator.has_next():
book = iterator.next()
print("书名:" + book.get_name())
🏗️ 架构级应用
把迭代器模式的思想从"遍历集合"放大到"遍历数据流",就变成了架构层面的数据流迭代器。
-
数据库结果集遍历:遍历数据库查询结果集,不需要了解数据库的内部实现
-
文件内容遍历:遍历大文件的内容,不需要一次性将整个文件加载到内存
-
消息队列消费:遍历消息队列中的消息,不需要了解消息队列的内部结构
-
分页查询:遍历分页查询的结果,不需要了解分页的具体实现
🏭 工业级中间件案例
-
Java集合框架:所有集合类都实现了Iterable接口,提供了iterator()方法
-
C#集合框架:所有集合类都实现了IEnumerable接口,提供了GetEnumerator()方法
-
Python迭代器:Python中的所有可迭代对象都实现了__iter__()和__next__()方法
-
JDBC ResultSet:数据库查询结果集,提供了next()方法遍历结果
-
Hibernate Query:Hibernate查询结果,提供了iterate()方法遍历结果
⚠️ 实战优化避坑(三语完整实现)
坑点1:迭代器失效问题
问题:在遍历过程中修改集合会导致迭代器失效
解决方案:使用迭代器的remove()方法删除元素,或者使用并发安全的集合类
// 正确的删除方式
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (item.equals("要删除的元素")) {
iterator.remove(); // 使用迭代器的remove方法
}
}
坑点2:与foreach循环的关系
问题:现在大多数语言都提供了foreach循环,迭代器模式似乎已经过时了
解决方案:foreach循环本质上就是迭代器模式的语法糖,编译器会自动将foreach循环转换成迭代器调用
坑点3:单向迭代器限制
问题:标准迭代器只能向前遍历,不能向后遍历
解决方案:实现双向迭代器(ListIterator),支持向前和向后遍历
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:迭代器接口、聚合接口 |
| 架构级 | 数据库结果集遍历、文件内容遍历、消息队列消费、分页查询 |
| 工业级 | Java集合框架、C#集合框架、Python迭代器、JDBC ResultSet |
第17章 享元模式(Flyweight)- 结构型
核心一句话:运用共享技术有效地支持大量细粒度的对象
🏠 生活真实故事
你去打印店打印一份文档:
-
文档中有很多相同的字符,比如"a"、“b”、“c”
-
如果每个字符都单独创建一个对象,会占用大量内存
-
实际上,所有的"a"都是一样的,所有的"b"也是一样的
-
打印店只需要为每个不同的字符创建一个对象,然后重复使用这些对象
这样,无论文档中有多少个"a",都只需要一个"a"对象,大大节省了内存。
📚 文科类比
-
汉字印刷:印刷术使用活字,每个汉字只需要一个活字,然后重复使用
-
公共交通:公交车、地铁等公共交通工具被很多人共享使用
-
图书馆书籍:一本书被很多人借阅,不需要每个人都买一本
-
共享经济:共享单车、共享充电宝等共享物品被很多人使用
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 享元接口 ==============
interface Character {
void display(String font, int size);
}
// ============== 具体享元 ==============
class ConcreteCharacter implements Character {
private char symbol; // 内部状态:字符本身,共享
public ConcreteCharacter(char symbol) {
this.symbol = symbol;
}
@Override
public void display(String font, int size) {
System.out.println("字符:" + symbol + ",字体:" + font + ",字号:" + size);
}
}
// ============== 享元工厂 ==============
class CharacterFactory {
private Map<Character, Character> characters = new HashMap<>();
public Character getCharacter(char symbol) {
Character character = characters.get(symbol);
if (character == null) {
character = new ConcreteCharacter(symbol);
characters.put(symbol, character);
System.out.println("创建新字符:" + symbol);
}
return character;
}
public int getCharacterCount() {
return characters.size();
}
}
// ============== 测试类 ==============
public class FlyweightTest {
public static void main(String[] args) {
CharacterFactory factory = new CharacterFactory();
// 创建多个字符对象
Character a1 = factory.getCharacter('a');
Character a2 = factory.getCharacter('a');
Character b1 = factory.getCharacter('b');
Character b2 = factory.getCharacter('b');
Character c1 = factory.getCharacter('c');
// 显示字符,传入外部状态
a1.display("宋体", 12);
a2.display("黑体", 16);
b1.display("楷体", 14);
b2.display("宋体", 12);
c1.display("黑体", 16);
System.out.println("创建的字符对象数量:" + factory.getCharacterCount());
}
}
C# 经典实现
// ============== 享元接口 ==============
public interface ICharacter
{
void Display(string font, int size);
}
// ============== 具体享元 ==============
public class ConcreteCharacter : ICharacter
{
private char _symbol; // 内部状态:字符本身,共享
public ConcreteCharacter(char symbol)
{
_symbol = symbol;
}
public void Display(string font, int size)
{
Console.WriteLine("字符:" + _symbol + ",字体:" + font + ",字号:" + size);
}
}
// ============== 享元工厂 ==============
public class CharacterFactory
{
private Dictionary<char, ICharacter> _characters = new Dictionary<char, ICharacter>();
public ICharacter GetCharacter(char symbol)
{
ICharacter character;
if (!_characters.TryGetValue(symbol, out character))
{
character = new ConcreteCharacter(symbol);
_characters.Add(symbol, character);
Console.WriteLine("创建新字符:" + symbol);
}
return character;
}
public int GetCharacterCount()
{
return _characters.Count;
}
}
// ============== 测试类 ==============
public class FlyweightTest
{
public static void Main()
{
CharacterFactory factory = new CharacterFactory();
// 创建多个字符对象
ICharacter a1 = factory.GetCharacter('a');
ICharacter a2 = factory.GetCharacter('a');
ICharacter b1 = factory.GetCharacter('b');
ICharacter b2 = factory.GetCharacter('b');
ICharacter c1 = factory.GetCharacter('c');
// 显示字符,传入外部状态
a1.Display("宋体", 12);
a2.Display("黑体", 16);
b1.Display("楷体", 14);
b2.Display("宋体", 12);
c1.Display("黑体", 16);
Console.WriteLine("创建的字符对象数量:" + factory.GetCharacterCount());
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 享元接口 ==============
class Character(ABC):
@abstractmethod
def display(self, font, size):
pass
# ============== 具体享元 ==============
class ConcreteCharacter(Character):
def __init__(self, symbol):
self.symbol = symbol # 内部状态:字符本身,共享
def display(self, font, size):
print(f"字符:{self.symbol},字体:{font},字号:{size}")
# ============== 享元工厂 ==============
class CharacterFactory:
def __init__(self):
self.characters = {}
def get_character(self, symbol):
if symbol not in self.characters:
self.characters[symbol] = ConcreteCharacter(symbol)
print(f"创建新字符:{symbol}")
return self.characters[symbol]
def get_character_count(self):
return len(self.characters)
# ============== 测试代码 ==============
if __name__ == "__main__":
factory = CharacterFactory()
# 创建多个字符对象
a1 = factory.get_character('a')
a2 = factory.get_character('a')
b1 = factory.get_character('b')
b2 = factory.get_character('b')
c1 = factory.get_character('c')
# 显示字符,传入外部状态
a1.display("宋体", 12)
a2.display("黑体", 16)
b1.display("楷体", 14)
b2.display("宋体", 12)
c1.display("黑体", 16)
print("创建的字符对象数量:", factory.get_character_count())
🏗️ 架构级应用
把享元模式的思想从"共享字符对象"放大到"共享系统资源",就变成了架构层面的资源池技术。
-
数据库连接池:共享数据库连接对象,避免频繁创建和销毁连接
-
线程池:共享线程对象,避免频繁创建和销毁线程
-
缓存系统:共享缓存数据,避免重复计算和查询
-
对象池:共享创建成本高的对象,如网络连接、文件句柄等
🏭 工业级中间件案例
-
Java String常量池:所有字符串字面量都存储在常量池中,实现自动共享
-
Java Integer缓存池:缓存-128到127之间的Integer对象
-
数据库连接池(C3P0、Druid):共享数据库连接对象
-
线程池(ThreadPoolExecutor):共享线程对象
-
Redis缓存:共享缓存数据,提高系统性能
⚠️ 实战优化避坑(三语完整实现)
坑点1:内部状态与外部状态混淆
问题:将外部状态存储在享元对象中,导致享元对象无法共享
解决方案:严格区分内部状态和外部状态,内部状态存储在享元对象中,外部状态由客户端传入
坑点2:享元工厂线程安全问题
问题:多线程环境下,享元工厂可能会创建重复的享元对象
解决方案:使用双重检查锁定(DCL)保证享元工厂的线程安全
// 线程安全的享元工厂
public class CharacterFactory {
private Map<Character, Character> characters = new ConcurrentHashMap<>();
public Character getCharacter(char symbol) {
Character character = characters.get(symbol);
if (character == null) {
synchronized (this) {
character = characters.get(symbol);
if (character == null) {
character = new ConcreteCharacter(symbol);
characters.put(symbol, character);
System.out.println("创建新字符:" + symbol);
}
}
}
return character;
}
}
坑点3:过度使用享元模式
问题:为了节省内存而过度使用享元模式,导致系统复杂度增加
解决方案:只有当系统中有大量相似对象且造成内存浪费时,才使用享元模式
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:享元接口、享元工厂 |
| 架构级 | 数据库连接池、线程池、缓存系统、对象池 |
| 工业级 | Java String常量池、Integer缓存池、C3P0连接池、Redis缓存 |
第18章 桥接模式(Bridge)- 结构型
核心一句话:将抽象部分与它的实现部分分离,使它们都可以独立地变化
🏠 生活真实故事
你有一部手机和多个充电器:
-
手机有不同的品牌:苹果、华为、小米
-
充电器有不同的类型:有线充电器、无线充电器、车载充电器
如果每个品牌的手机都需要对应一个特定类型的充电器,那么就会有:
3(手机品牌) × 3(充电器类型) = 9 种组合
但是实际上,手机和充电器是可以独立变化的:
-
你可以用任何品牌的有线充电器给任何品牌的手机充电
-
你可以用任何品牌的无线充电器给任何支持无线充电的手机充电
在这里,手机和充电器之间通过充电接口这座桥连接起来,它们可以独立变化。
📚 文科类比
-
电视和遥控器:电视有不同的品牌,遥控器有不同的类型,它们通过红外接口连接
-
汽车和轮胎:汽车有不同的品牌,轮胎有不同的品牌,它们通过轮毂连接
-
人和衣服:人有不同的体型,衣服有不同的款式,它们通过尺寸连接
-
笔和纸:笔有不同的类型,纸有不同的规格,它们通过书写接口连接
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 实现部分接口:充电器 ==============
interface Charger {
void charge();
}
// ============== 具体实现:有线充电器 ==============
class WiredCharger implements Charger {
@Override
public void charge() {
System.out.println("使用有线充电器充电");
}
}
// ============== 具体实现:无线充电器 ==============
class WirelessCharger implements Charger {
@Override
public void charge() {
System.out.println("使用无线充电器充电");
}
}
// ============== 抽象部分:手机 ==============
abstract class Phone {
protected Charger charger;
public Phone(Charger charger) {
this.charger = charger;
}
public abstract void charge();
}
// ============== 具体抽象:苹果手机 ==============
class IPhone extends Phone {
public IPhone(Charger charger) {
super(charger);
}
@Override
public void charge() {
System.out.print("苹果手机 ");
charger.charge();
}
}
// ============== 具体抽象:华为手机 ==============
class HuaweiPhone extends Phone {
public HuaweiPhone(Charger charger) {
super(charger);
}
@Override
public void charge() {
System.out.print("华为手机 ");
charger.charge();
}
}
// ============== 测试类 ==============
public class BridgeTest {
public static void main(String[] args) {
// 苹果手机使用有线充电器
Charger wiredCharger = new WiredCharger();
Phone iPhone = new IPhone(wiredCharger);
iPhone.charge();
// 华为手机使用无线充电器
Charger wirelessCharger = new WirelessCharger();
Phone huaweiPhone = new HuaweiPhone(wirelessCharger);
huaweiPhone.charge();
// 苹果手机使用无线充电器
Phone iPhoneWireless = new IPhone(wirelessCharger);
iPhoneWireless.charge();
}
}
C# 经典实现
// ============== 实现部分接口:充电器 ==============
public interface ICharger
{
void Charge();
}
// ============== 具体实现:有线充电器 ==============
public class WiredCharger : ICharger
{
public void Charge()
{
Console.WriteLine("使用有线充电器充电");
}
}
// ============== 具体实现:无线充电器 ==============
public class WirelessCharger : ICharger
{
public void Charge()
{
Console.WriteLine("使用无线充电器充电");
}
}
// ============== 抽象部分:手机 ==============
public abstract class Phone
{
protected ICharger _charger;
public Phone(ICharger charger)
{
_charger = charger;
}
public abstract void Charge();
}
// ============== 具体抽象:苹果手机 ==============
public class IPhone : Phone
{
public IPhone(ICharger charger) : base(charger) { }
public override void Charge()
{
Console.Write("苹果手机 ");
_charger.Charge();
}
}
// ============== 具体抽象:华为手机 ==============
public class HuaweiPhone : Phone
{
public HuaweiPhone(ICharger charger) : base(charger) { }
public override void Charge()
{
Console.Write("华为手机 ");
_charger.Charge();
}
}
// ============== 测试类 ==============
public class BridgeTest
{
public static void Main()
{
// 苹果手机使用有线充电器
ICharger wiredCharger = new WiredCharger();
Phone iPhone = new IPhone(wiredCharger);
iPhone.Charge();
// 华为手机使用无线充电器
ICharger wirelessCharger = new WirelessCharger();
Phone huaweiPhone = new HuaweiPhone(wirelessCharger);
huaweiPhone.Charge();
// 苹果手机使用无线充电器
Phone iPhoneWireless = new IPhone(wirelessCharger);
iPhoneWireless.Charge();
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 实现部分接口:充电器 ==============
class Charger(ABC):
@abstractmethod
def charge(self):
pass
# ============== 具体实现:有线充电器 ==============
class WiredCharger(Charger):
def charge(self):
print("使用有线充电器充电")
# ============== 具体实现:无线充电器 ==============
class WirelessCharger(Charger):
def charge(self):
print("使用无线充电器充电")
# ============== 抽象部分:手机 ==============
class Phone(ABC):
def __init__(self, charger):
self.charger = charger
@abstractmethod
def charge(self):
pass
# ============== 具体抽象:苹果手机 ==============
class IPhone(Phone):
def charge(self):
print("苹果手机 ", end="")
self.charger.charge()
# ============== 具体抽象:华为手机 ==============
class HuaweiPhone(Phone):
def charge(self):
print("华为手机 ", end="")
self.charger.charge()
# ============== 测试代码 ==============
if __name__ == "__main__":
# 苹果手机使用有线充电器
wired_charger = WiredCharger()
iphone = IPhone(wired_charger)
iphone.charge()
# 华为手机使用无线充电器
wireless_charger = WirelessCharger()
huawei_phone = HuaweiPhone(wireless_charger)
huawei_phone.charge()
# 苹果手机使用无线充电器
iphone_wireless = IPhone(wireless_charger)
iphone_wireless.charge()
🏗️ 架构级应用
把桥接模式的思想从"手机和充电器"放大到"系统架构",就变成了架构层面的多层架构。
-
前后端分离:前端和后端通过API接口连接,它们可以独立开发和部署
-
数据库访问层:业务逻辑和数据库访问通过DAO接口连接,它们可以独立变化
-
消息队列:生产者和消费者通过消息队列连接,它们可以独立部署和扩展
-
微服务架构:各个微服务通过API网关连接,它们可以独立开发和部署
🏭 工业级中间件案例
-
JDBC:Java应用程序和数据库通过JDBC接口连接,不同数据库有不同的JDBC驱动
-
SLF4J:应用程序和日志框架通过SLF4J接口连接,支持不同的日志实现
-
Spring ORM:Spring和ORM框架通过ORM接口连接,支持Hibernate、MyBatis等不同的ORM实现
-
Java NIO:Java应用程序和操作系统通过NIO接口连接,支持不同的操作系统
-
Android系统架构:应用层和系统层通过Binder机制连接,它们可以独立更新
⚠️ 实战优化避坑(三语完整实现)
坑点1:与适配器模式混淆
问题:桥接模式和适配器模式结构相似,容易混淆
解决方案:
-
桥接模式:事前设计,将抽象和实现分离,让它们可以独立变化
-
适配器模式:事后补救,解决已经存在的接口不兼容问题
坑点2:桥接层次过多问题
问题:桥接层次过多会导致系统复杂度增加
解决方案:合理设计桥接层次,一般不超过两层
坑点3:抽象与实现的划分问题
问题:抽象和实现的划分不当会导致桥接模式失去意义
解决方案:将稳定的部分作为抽象,将变化的部分作为实现
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:抽象部分、实现部分 |
| 架构级 | 前后端分离、数据库访问层、消息队列、微服务架构 |
| 工业级 | JDBC、SLF4J、Spring ORM、Java NIO |
第19章 备忘录模式(Memento)- 行为型
核心一句话:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
🏠 生活真实故事
你在玩一款游戏:
-
游戏中有很多关卡,每个关卡都很难
-
如果你在某个关卡失败了,需要从头开始玩,会非常浪费时间
-
于是游戏提供了存档功能:
-
你可以在通过一个关卡后保存游戏进度
-
如果你在下一个关卡失败了,可以读取存档,从上次保存的地方继续玩
-
存档中保存了你的角色等级、装备、金币等所有状态信息
-
📚 文科类比
-
文档撤销功能:你可以撤销之前的编辑操作,恢复到之前的文档状态
-
数据库备份:你可以备份数据库,在数据丢失时恢复到备份时的状态
-
时光胶囊:你可以把现在的东西埋在地下,多年后挖出来,回忆过去的时光
-
照片:照片记录了某个时刻的场景,你可以通过照片回忆当时的情景
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 备忘录类 ==============
class GameMemento {
private int level;
private int score;
private String weapon;
public GameMemento(int level, int score, String weapon) {
this.level = level;
this.score = score;
this.weapon = weapon;
}
// 只有原发器可以访问备忘录的状态
int getLevel() {
return level;
}
int getScore() {
return score;
}
String getWeapon() {
return weapon;
}
}
// ============== 原发器类:游戏角色 ==============
class GameCharacter {
private int level;
private int score;
private String weapon;
public void setLevel(int level) {
this.level = level;
}
public void setScore(int score) {
this.score = score;
}
public void setWeapon(String weapon) {
this.weapon = weapon;
}
// 创建备忘录,保存当前状态
public GameMemento saveState() {
return new GameMemento(level, score, weapon);
}
// 从备忘录恢复状态
public void restoreState(GameMemento memento) {
this.level = memento.getLevel();
this.score = memento.getScore();
this.weapon = memento.getWeapon();
}
// 显示当前状态
public void displayState() {
System.out.println("当前状态:等级=" + level + ",分数=" + score + ",武器=" + weapon);
}
}
// ============== 管理者类:存档管理器 ==============
class SaveManager {
private GameMemento memento;
public void saveMemento(GameMemento memento) {
this.memento = memento;
}
public GameMemento getMemento() {
return memento;
}
}
// ============== 测试类 ==============
public class MementoTest {
public static void main(String[] args) {
GameCharacter character = new GameCharacter();
SaveManager saveManager = new SaveManager();
// 初始状态
character.setLevel(1);
character.setScore(0);
character.setWeapon("木剑");
System.out.println("=== 初始状态 ===");
character.displayState();
// 保存状态
saveManager.saveMemento(character.saveState());
// 升级
character.setLevel(5);
character.setScore(1000);
character.setWeapon("铁剑");
System.out.println("\n=== 升级后状态 ===");
character.displayState();
// 恢复到之前的状态
character.restoreState(saveManager.getMemento());
System.out.println("\n=== 恢复后状态 ===");
character.displayState();
}
}
C# 经典实现
// ============== 备忘录类 ==============
public class GameMemento
{
public int Level { get; private set; }
public int Score { get; private set; }
public string Weapon { get; private set; }
public GameMemento(int level, int score, string weapon)
{
Level = level;
Score = score;
Weapon = weapon;
}
}
// ============== 原发器类:游戏角色 ==============
public class GameCharacter
{
public int Level { get; set; }
public int Score { get; set; }
public string Weapon { get; set; }
// 创建备忘录,保存当前状态
public GameMemento SaveState()
{
return new GameMemento(Level, Score, Weapon);
}
// 从备忘录恢复状态
public void RestoreState(GameMemento memento)
{
Level = memento.Level;
Score = memento.Score;
Weapon = memento.Weapon;
}
// 显示当前状态
public void DisplayState()
{
Console.WriteLine("当前状态:等级=" + Level + ",分数=" + Score + ",武器=" + Weapon);
}
}
// ============== 管理者类:存档管理器 ==============
public class SaveManager
{
public GameMemento Memento { get; set; }
}
// ============== 测试类 ==============
public class MementoTest
{
public static void Main()
{
GameCharacter character = new GameCharacter();
SaveManager saveManager = new SaveManager();
// 初始状态
character.Level = 1;
character.Score = 0;
character.Weapon = "木剑";
Console.WriteLine("=== 初始状态 ===");
character.DisplayState();
// 保存状态
saveManager.Memento = character.SaveState();
// 升级
character.Level = 5;
character.Score = 1000;
character.Weapon = "铁剑";
Console.WriteLine("\n=== 升级后状态 ===");
character.DisplayState();
// 恢复到之前的状态
character.RestoreState(saveManager.Memento);
Console.WriteLine("\n=== 恢复后状态 ===");
character.DisplayState();
}
}
Python 经典实现
# ============== 备忘录类 ==============
class GameMemento:
def __init__(self, level, score, weapon):
self._level = level
self._score = score
self._weapon = weapon
@property
def level(self):
return self._level
@property
def score(self):
return self._score
@property
def weapon(self):
return self._weapon
# ============== 原发器类:游戏角色 ==============
class GameCharacter:
def __init__(self):
self.level = 1
self.score = 0
self.weapon = "木剑"
# 创建备忘录,保存当前状态
def save_state(self):
return GameMemento(self.level, self.score, self.weapon)
# 从备忘录恢复状态
def restore_state(self, memento):
self.level = memento.level
self.score = memento.score
self.weapon = memento.weapon
# 显示当前状态
def display_state(self):
print(f"当前状态:等级={self.level},分数={self.score},武器={self.weapon}")
# ============== 管理者类:存档管理器 ==============
class SaveManager:
def __init__(self):
self.memento = None
# ============== 测试代码 ==============
if __name__ == "__main__":
character = GameCharacter()
save_manager = SaveManager()
# 初始状态
print("=== 初始状态 ===")
character.display_state()
# 保存状态
save_manager.memento = character.save_state()
# 升级
character.level = 5
character.score = 1000
character.weapon = "铁剑"
print("\n=== 升级后状态 ===")
character.display_state()
# 恢复到之前的状态
character.restore_state(save_manager.memento)
print("\n=== 恢复后状态 ===")
character.display_state()
🏗️ 架构级应用
把备忘录模式的思想从"游戏存档"放大到"系统状态管理",就变成了架构层面的状态快照技术。
-
数据库事务回滚:在事务执行前保存数据库状态,事务失败时回滚到之前的状态
-
版本控制系统(Git):保存文件的历史版本,可以随时恢复到任意版本
-
虚拟机快照:保存虚拟机的状态,可以随时恢复到快照时的状态
-
系统备份:保存整个系统的状态,在系统崩溃时恢复到备份时的状态
🏭 工业级中间件案例
-
Git:分布式版本控制系统,保存文件的历史版本
-
数据库事务:支持事务回滚,恢复到事务开始前的状态
-
Word/Excel撤销功能:支持多级撤销,恢复到之前的编辑状态
-
Photoshop历史记录:保存编辑历史,可以随时撤销操作
-
虚拟机软件(VMware/VirtualBox):支持创建虚拟机快照,恢复虚拟机状态
⚠️ 实战优化避坑(三语完整实现)
坑点1:备忘录对象过大问题
问题:如果原发器对象状态很多,备忘录对象会占用大量内存
解决方案:只保存关键状态,或者使用增量备份方式
坑点2:封装性破坏问题
问题:如果备忘录对象的状态被外部修改,会破坏封装性
解决方案:将备忘录类的构造函数和getter方法设置为包访问权限,只有原发器可以访问
坑点3:多状态备份问题
问题:需要保存多个历史状态时,管理起来会很复杂
解决方案:使用栈结构保存多个备忘录对象,支持多级撤销
// 支持多级撤销的存档管理器
class SaveManager {
private Stack<GameMemento> mementos = new Stack<>();
public void saveMemento(GameMemento memento) {
mementos.push(memento);
}
public GameMemento getMemento() {
if (!mementos.isEmpty()) {
return mementos.pop();
}
return null;
}
}
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心三要素:备忘录类、原发器类、管理者类 |
| 架构级 | 数据库事务回滚、版本控制系统、虚拟机快照、系统备份 |
| 工业级 | Git、数据库事务、Word撤销功能、Photoshop历史记录 |
第三阶6个设计模式速查表
| 模式名称 | 类别 | 核心一句话 | 生活场景 | 工业级案例 |
|---|---|---|---|---|
| 抽象工厂模式 | 创建型 | 创建一组相关的对象,保证产品族一致性 | 家具品牌店、汽车4S店 | Java AWT、MyBatis SqlSessionFactory、JDBC DriverManager |
| 组合模式 | 结构型 | 统一处理树形结构中的单个对象和组合对象 | 文件系统、公司组织架构 | Java Swing、Android View系统、HTML DOM |
| 迭代器模式 | 行为型 | 提供统一的方式遍历集合,不暴露内部结构 | 图书馆借书、导游带团 | Java集合框架、C#集合框架、JDBC ResultSet |
| 享元模式 | 结构型 | 共享细粒度对象,减少内存占用 | 汉字印刷、公共交通 | Java String常量池、数据库连接池、Redis缓存 |
| 桥接模式 | 结构型 | 分离抽象与实现,解决多维度变化导致的类爆炸 | 手机与充电器、电视与遥控器 | JDBC、SLF4J、Spring ORM |
| 备忘录模式 | 行为型 | 保存和恢复对象状态,实现撤销/存档功能 | 游戏存档、文档撤销 | Git、数据库事务、Word撤销功能 |
需要我把这6个模式和之前的8个模式合并成一个完整的14个设计模式速查表,方便你统一查阅吗?
23个设计模式全集(完结篇)
统一讲解结构:生活真实故事 → 文科类比 → 三语标准OOP代码 → 架构级应用 → 工业级中间件案例 → 实战优化避坑(三语完整实现)→ 本课总结
第20章 中介者模式(Mediator)- 行为型
核心一句话:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
🏠 生活真实故事
你公司有10个部门:研发、产品、设计、测试、运营、市场、人事、财务、行政、客服。
如果没有中介者:
-
研发需要和产品、设计、测试、运营沟通
-
产品需要和研发、设计、测试、市场沟通
-
每个部门都要和其他多个部门直接联系
-
整个公司变成了一个复杂的网状结构,沟通成本极高
有了**项目经理(中介者)**之后:
-
所有部门只需要和项目经理沟通
-
项目经理负责协调各个部门之间的工作
-
部门之间不需要直接联系
-
整个公司变成了一个简单的星型结构,沟通成本大大降低
📚 文科类比
-
机场塔台:所有飞机只需要和塔台通信,不需要和其他飞机直接通信
-
微信群主:群成员只需要在群里发言,群主负责协调群内事务
-
房产中介:买家和卖家不需要直接联系,所有事情都通过中介处理
-
联合国:各个国家不需要直接谈判,通过联合国进行沟通和协调
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象中介者 ==============
interface Mediator {
void send(String message, Colleague colleague);
}
// ============== 抽象同事类 ==============
abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public abstract void receive(String message);
public abstract void send(String message);
}
// ============== 具体中介者:项目经理 ==============
class ProjectManager implements Mediator {
private Developer developer;
private Designer designer;
private Tester tester;
public void setDeveloper(Developer developer) {
this.developer = developer;
}
public void setDesigner(Designer designer) {
this.designer = designer;
}
public void setTester(Tester tester) {
this.tester = tester;
}
@Override
public void send(String message, Colleague colleague) {
if (colleague == developer) {
designer.receive(message);
tester.receive(message);
} else if (colleague == designer) {
developer.receive(message);
tester.receive(message);
} else if (colleague == tester) {
developer.receive(message);
designer.receive(message);
}
}
}
// ============== 具体同事类 ==============
class Developer extends Colleague {
public Developer(Mediator mediator) {
super(mediator);
}
@Override
public void receive(String message) {
System.out.println("开发收到:" + message);
}
@Override
public void send(String message) {
System.out.println("开发发送:" + message);
mediator.send(message, this);
}
}
class Designer extends Colleague {
public Designer(Mediator mediator) {
super(mediator);
}
@Override
public void receive(String message) {
System.out.println("设计收到:" + message);
}
@Override
public void send(String message) {
System.out.println("设计发送:" + message);
mediator.send(message, this);
}
}
class Tester extends Colleague {
public Tester(Mediator mediator) {
super(mediator);
}
@Override
public void receive(String message) {
System.out.println("测试收到:" + message);
}
@Override
public void send(String message) {
System.out.println("测试发送:" + message);
mediator.send(message, this);
}
}
// ============== 测试类 ==============
public class MediatorTest {
public static void main(String[] args) {
ProjectManager pm = new ProjectManager();
Developer dev = new Developer(pm);
Designer des = new Designer(pm);
Tester test = new Tester(pm);
pm.setDeveloper(dev);
pm.setDesigner(des);
pm.setTester(test);
dev.send("需求开发完成");
System.out.println();
des.send("设计稿已更新");
}
}
C# 经典实现
// ============== 抽象中介者 ==============
public interface IMediator
{
void Send(string message, Colleague colleague);
}
// ============== 抽象同事类 ==============
public abstract class Colleague
{
protected IMediator _mediator;
public Colleague(IMediator mediator)
{
_mediator = mediator;
}
public abstract void Receive(string message);
public abstract void Send(string message);
}
// ============== 具体中介者:项目经理 ==============
public class ProjectManager : IMediator
{
public Developer Developer { get; set; }
public Designer Designer { get; set; }
public Tester Tester { get; set; }
public void Send(string message, Colleague colleague)
{
if (colleague == Developer)
{
Designer.Receive(message);
Tester.Receive(message);
}
else if (colleague == Designer)
{
Developer.Receive(message);
Tester.Receive(message);
}
else if (colleague == Tester)
{
Developer.Receive(message);
Designer.Receive(message);
}
}
}
// ============== 具体同事类 ==============
public class Developer : Colleague
{
public Developer(IMediator mediator) : base(mediator) { }
public override void Receive(string message)
{
Console.WriteLine("开发收到:" + message);
}
public override void Send(string message)
{
Console.WriteLine("开发发送:" + message);
_mediator.Send(message, this);
}
}
public class Designer : Colleague
{
public Designer(IMediator mediator) : base(mediator) { }
public override void Receive(string message)
{
Console.WriteLine("设计收到:" + message);
}
public override void Send(string message)
{
Console.WriteLine("设计发送:" + message);
_mediator.Send(message, this);
}
}
public class Tester : Colleague
{
public Tester(IMediator mediator) : base(mediator) { }
public override void Receive(string message)
{
Console.WriteLine("测试收到:" + message);
}
public override void Send(string message)
{
Console.WriteLine("测试发送:" + message);
_mediator.Send(message, this);
}
}
// ============== 测试类 ==============
public class MediatorTest
{
public static void Main()
{
ProjectManager pm = new ProjectManager();
Developer dev = new Developer(pm);
Designer des = new Designer(pm);
Tester test = new Tester(pm);
pm.Developer = dev;
pm.Designer = des;
pm.Tester = test;
dev.Send("需求开发完成");
Console.WriteLine();
des.Send("设计稿已更新");
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象中介者 ==============
class Mediator(ABC):
@abstractmethod
def send(self, message, colleague):
pass
# ============== 抽象同事类 ==============
class Colleague(ABC):
def __init__(self, mediator):
self.mediator = mediator
@abstractmethod
def receive(self, message):
pass
@abstractmethod
def send(self, message):
pass
# ============== 具体中介者:项目经理 ==============
class ProjectManager(Mediator):
def __init__(self):
self.developer = None
self.designer = None
self.tester = None
def send(self, message, colleague):
if colleague == self.developer:
self.designer.receive(message)
self.tester.receive(message)
elif colleague == self.designer:
self.developer.receive(message)
self.tester.receive(message)
elif colleague == self.tester:
self.developer.receive(message)
self.designer.receive(message)
# ============== 具体同事类 ==============
class Developer(Colleague):
def receive(self, message):
print(f"开发收到:{message}")
def send(self, message):
print(f"开发发送:{message}")
self.mediator.send(message, self)
class Designer(Colleague):
def receive(self, message):
print(f"设计收到:{message}")
def send(self, message):
print(f"设计发送:{message}")
self.mediator.send(message, self)
class Tester(Colleague):
def receive(self, message):
print(f"测试收到:{message}")
def send(self, message):
print(f"测试发送:{message}")
self.mediator.send(message, self)
# ============== 测试代码 ==============
if __name__ == "__main__":
pm = ProjectManager()
dev = Developer(pm)
des = Designer(pm)
test = Tester(pm)
pm.developer = dev
pm.designer = des
pm.tester = test
dev.send("需求开发完成")
print()
des.send("设计稿已更新")
🏗️ 架构级应用
把中介者模式的思想从"协调对象交互"放大到"协调服务交互",就变成了架构层面的消息中间件/服务总线。
-
消息队列:服务之间通过消息队列进行通信,不需要直接调用
-
服务总线:微服务之间通过服务总线进行通信,实现解耦
-
事件总线:系统内部通过事件总线发布和订阅事件
-
API网关:作为所有服务的统一入口,协调服务之间的调用
🏭 工业级中间件案例
-
RocketMQ/Kafka/RabbitMQ:消息队列,实现服务之间的异步通信
-
Spring Cloud Bus:事件总线,实现微服务之间的事件通信
-
MVC模式中的Controller:作为Model和View之间的中介者
-
Android中的Intent:作为组件之间通信的中介者
-
WebSocket服务器:作为客户端之间通信的中介者
⚠️ 实战优化避坑(三语完整实现)
坑点1:中介者类膨胀问题
问题:中介者类包含了太多的协调逻辑,变成了"上帝类"
解决方案:
-
将中介者拆分成多个子中介者,每个子中介者负责一部分协调逻辑
-
使用观察者模式结合中介者模式,减少中介者的复杂度
// 使用观察者模式简化中介者
class EventMediator {
private Map<String, List<Colleague>> listeners = new HashMap<>();
public void register(String event, Colleague colleague) {
if (!listeners.containsKey(event)) {
listeners.put(event, new ArrayList<>());
}
listeners.get(event).add(colleague);
}
public void publish(String event, String message) {
if (listeners.containsKey(event)) {
for (Colleague colleague : listeners.get(event)) {
colleague.receive(message);
}
}
}
}
坑点2:与外观模式混淆
问题:中介者模式和外观模式结构相似,容易混淆
解决方案:
-
中介者模式:双向通信,同事类可以向中介者发送消息,也可以接收中介者的消息
-
外观模式:单向通信,客户端只能调用外观类的方法,外观类不能调用客户端的方法
坑点3:过度使用中介者模式
问题:为了解耦而过度使用中介者,导致系统变得复杂
解决方案:只有当对象之间的交互非常复杂且难以维护时,才使用中介者模式
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:抽象中介者、抽象同事类 |
| 架构级 | 消息队列、服务总线、事件总线、API网关 |
| 工业级 | RocketMQ/Kafka、Spring Cloud Bus、MVC Controller |
第21章 访问者模式(Visitor)- 行为型
核心一句话:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
🏠 生活真实故事
你家有很多家具:沙发、桌子、椅子、床。
不同的人来你家,对这些家具做不同的操作:
-
清洁工:擦沙发、擦桌子、擦椅子、擦床
-
搬家工人:搬沙发、搬桌子、搬椅子、搬床
-
维修工人:修沙发、修桌子、修椅子、修床
如果不用访问者模式:
-
每个家具类都要添加clean()、move()、repair()方法
-
以后再来一个"油漆工",需要修改所有家具类
-
违反了开闭原则
用了访问者模式之后:
-
每个访问者类实现对所有家具的操作
-
以后再来新的访问者,只需要添加一个新的访问者类
-
不需要修改任何家具类,符合开闭原则
📚 文科类比
-
医生看病:医生对不同的病人(小孩、老人、孕妇)做不同的检查和治疗
-
审计员查账:审计员对不同的账目(收入、支出、资产)做不同的审计
-
导游带团:导游对不同的景点(博物馆、公园、古迹)做不同的讲解
-
海关检查:海关对不同的物品(行李、货物、邮件)做不同的检查
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象元素 ==============
interface Furniture {
void accept(Visitor visitor);
}
// ============== 具体元素 ==============
class Sofa implements Furniture {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class Table implements Furniture {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class Chair implements Furniture {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// ============== 抽象访问者 ==============
interface Visitor {
void visit(Sofa sofa);
void visit(Table table);
void visit(Chair chair);
}
// ============== 具体访问者 ==============
class Cleaner implements Visitor {
@Override
public void visit(Sofa sofa) {
System.out.println("清洁工擦沙发");
}
@Override
public void visit(Table table) {
System.out.println("清洁工擦桌子");
}
@Override
public void visit(Chair chair) {
System.out.println("清洁工擦椅子");
}
}
class Mover implements Visitor {
@Override
public void visit(Sofa sofa) {
System.out.println("搬家工人搬沙发");
}
@Override
public void visit(Table table) {
System.out.println("搬家工人搬桌子");
}
@Override
public void visit(Chair chair) {
System.out.println("搬家工人搬椅子");
}
}
// ============== 对象结构 ==============
class House {
private List<Furniture> furnitures = new ArrayList<>();
public void addFurniture(Furniture furniture) {
furnitures.add(furniture);
}
public void accept(Visitor visitor) {
for (Furniture furniture : furnitures) {
furniture.accept(visitor);
}
}
}
// ============== 测试类 ==============
public class VisitorTest {
public static void main(String[] args) {
House house = new House();
house.addFurniture(new Sofa());
house.addFurniture(new Table());
house.addFurniture(new Chair());
System.out.println("=== 清洁工来打扫 ===");
house.accept(new Cleaner());
System.out.println("\n=== 搬家工人来搬家 ===");
house.accept(new Mover());
}
}
C# 经典实现
// ============== 抽象元素 ==============
public interface IFurniture
{
void Accept(IVisitor visitor);
}
// ============== 具体元素 ==============
public class Sofa : IFurniture
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
public class Table : IFurniture
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
public class Chair : IFurniture
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
// ============== 抽象访问者 ==============
public interface IVisitor
{
void Visit(Sofa sofa);
void Visit(Table table);
void Visit(Chair chair);
}
// ============== 具体访问者 ==============
public class Cleaner : IVisitor
{
public void Visit(Sofa sofa)
{
Console.WriteLine("清洁工擦沙发");
}
public void Visit(Table table)
{
Console.WriteLine("清洁工擦桌子");
}
public void Visit(Chair chair)
{
Console.WriteLine("清洁工擦椅子");
}
}
public class Mover : IVisitor
{
public void Visit(Sofa sofa)
{
Console.WriteLine("搬家工人搬沙发");
}
public void Visit(Table table)
{
Console.WriteLine("搬家工人搬桌子");
}
public void Visit(Chair chair)
{
Console.WriteLine("搬家工人搬椅子");
}
}
// ============== 对象结构 ==============
public class House
{
private List<IFurniture> _furnitures = new List<IFurniture>();
public void AddFurniture(IFurniture furniture)
{
_furnitures.Add(furniture);
}
public void Accept(IVisitor visitor)
{
foreach (IFurniture furniture in _furnitures)
{
furniture.Accept(visitor);
}
}
}
// ============== 测试类 ==============
public class VisitorTest
{
public static void Main()
{
House house = new House();
house.AddFurniture(new Sofa());
house.AddFurniture(new Table());
house.AddFurniture(new Chair());
Console.WriteLine("=== 清洁工来打扫 ===");
house.Accept(new Cleaner());
Console.WriteLine("\n=== 搬家工人来搬家 ===");
house.Accept(new Mover());
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象元素 ==============
class Furniture(ABC):
@abstractmethod
def accept(self, visitor):
pass
# ============== 具体元素 ==============
class Sofa(Furniture):
def accept(self, visitor):
visitor.visit_sofa(self)
class Table(Furniture):
def accept(self, visitor):
visitor.visit_table(self)
class Chair(Furniture):
def accept(self, visitor):
visitor.visit_chair(self)
# ============== 抽象访问者 ==============
class Visitor(ABC):
@abstractmethod
def visit_sofa(self, sofa):
pass
@abstractmethod
def visit_table(self, table):
pass
@abstractmethod
def visit_chair(self, chair):
pass
# ============== 具体访问者 ==============
class Cleaner(Visitor):
def visit_sofa(self, sofa):
print("清洁工擦沙发")
def visit_table(self, table):
print("清洁工擦桌子")
def visit_chair(self, chair):
print("清洁工擦椅子")
class Mover(Visitor):
def visit_sofa(self, sofa):
print("搬家工人搬沙发")
def visit_table(self, table):
print("搬家工人搬桌子")
def visit_chair(self, chair):
print("搬家工人搬椅子")
# ============== 对象结构 ==============
class House:
def __init__(self):
self.furnitures = []
def add_furniture(self, furniture):
self.furnitures.append(furniture)
def accept(self, visitor):
for furniture in self.furnitures:
furniture.accept(visitor)
# ============== 测试代码 ==============
if __name__ == "__main__":
house = House()
house.add_furniture(Sofa())
house.add_furniture(Table())
house.add_furniture(Chair())
print("=== 清洁工来打扫 ===")
house.accept(Cleaner())
print("\n=== 搬家工人来搬家 ===")
house.accept(Mover())
🏗️ 架构级应用
把访问者模式的思想从"操作对象结构"放大到"操作数据结构",就变成了架构层面的数据处理管道。
-
抽象语法树(AST)处理:编译器对AST进行语法检查、代码生成、优化等操作
-
文档处理:对XML/JSON文档进行验证、转换、格式化等操作
-
报表生成:对不同的数据结构生成不同格式的报表(PDF、Excel、HTML)
-
规则引擎:对不同的数据对象应用不同的业务规则
🏭 工业级中间件案例
-
Java编译器:对Java源代码生成的AST进行各种处理
-
ANTLR:语法分析器生成器,使用访问者模式遍历语法树
-
Jackson/Gson:JSON解析库,使用访问者模式遍历JSON树
-
ASM/ByteBuddy:字节码操作库,使用访问者模式遍历字节码
-
JUnit 5:测试框架,使用访问者模式遍历测试用例
⚠️ 实战优化避坑(三语完整实现)
坑点1:元素结构变化困难
问题:如果需要添加新的元素类型,需要修改所有的访问者类
解决方案:只有当元素结构稳定而操作频繁变化时,才使用访问者模式
坑点2:破坏封装性
问题:访问者需要访问元素的内部状态,可能会破坏元素的封装性
解决方案:元素只暴露必要的接口给访问者,不要暴露内部实现细节
坑点3:代码可读性差
问题:访问者模式的代码结构比较复杂,可读性较差
解决方案:添加详细的注释,说明每个访问者和元素的作用
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心四要素:抽象元素、具体元素、抽象访问者、具体访问者 |
| 架构级 | AST处理、文档处理、报表生成、规则引擎 |
| 工业级 | Java编译器、ANTLR、Jackson/Gson、ASM/ByteBuddy |
第22章 原型模式(Prototype)- 创建型
核心一句话:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
🏠 生活真实故事
你需要打印100份相同的简历:
-
如果你手写100份,会非常累而且容易出错
-
你只需要写一份简历,然后复印99份
-
复印出来的简历和原件完全一样
-
你可以在复印好的简历上做一些小修改,比如不同公司的求职意向
📚 文科类比
-
印章:用印章可以盖出很多相同的印记
-
活字印刷:用活字可以印刷出很多相同的文字
-
模具:用模具可以制造出很多相同的产品
-
克隆技术:用一个细胞可以克隆出一个完全相同的生物
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 原型接口 ==============
interface Prototype extends Cloneable {
Prototype clone();
}
// ============== 具体原型 ==============
class Resume implements Prototype {
private String name;
private int age;
private String education;
public Resume(String name, int age, String education) {
this.name = name;
this.age = age;
this.education = education;
}
// 浅拷贝
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
// Getter和Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEducation() {
return education;
}
public void setEducation(String education) {
this.education = education;
}
@Override
public String toString() {
return "Resume{" +
"name='" + name + '\'' +
", age=" + age +
", education='" + education + '\'' +
'}';
}
}
// ============== 测试类 ==============
public class PrototypeTest {
public static void main(String[] args) {
// 创建原型对象
Resume prototype = new Resume("张三", 25, "本科");
// 克隆对象
Resume resume1 = (Resume) prototype.clone();
Resume resume2 = (Resume) prototype.clone();
// 修改克隆对象
resume1.setName("张三-应聘Java开发");
resume2.setName("张三-应聘Python开发");
System.out.println("原型:" + prototype);
System.out.println("克隆1:" + resume1);
System.out.println("克隆2:" + resume2);
}
}
C# 经典实现
// ============== 原型接口 ==============
public interface IPrototype
{
IPrototype Clone();
}
// ============== 具体原型 ==============
public class Resume : IPrototype
{
public string Name { get; set; }
public int Age { get; set; }
public string Education { get; set; }
public Resume(string name, int age, string education)
{
Name = name;
Age = age;
Education = education;
}
// 浅拷贝
public IPrototype Clone()
{
return (IPrototype) this.MemberwiseClone();
}
public override string ToString()
{
return $"Resume{{ Name='{Name}', Age={Age}, Education='{Education}' }}";
}
}
// ============== 测试类 ==============
public class PrototypeTest
{
public static void Main()
{
// 创建原型对象
Resume prototype = new Resume("张三", 25, "本科");
// 克隆对象
Resume resume1 = (Resume) prototype.Clone();
Resume resume2 = (Resume) prototype.Clone();
// 修改克隆对象
resume1.Name = "张三-应聘Java开发";
resume2.Name = "张三-应聘Python开发";
Console.WriteLine("原型:" + prototype);
Console.WriteLine("克隆1:" + resume1);
Console.WriteLine("克隆2:" + resume2);
}
}
Python 经典实现
import copy
# ============== 具体原型 ==============
class Resume:
def __init__(self, name, age, education):
self.name = name
self.age = age
self.education = education
# 浅拷贝
def clone(self):
return copy.copy(self)
# 深拷贝
def deep_clone(self):
return copy.deepcopy(self)
def __str__(self):
return f"Resume{{ name='{self.name}', age={self.age}, education='{self.education}' }}"
# ============== 测试代码 ==============
if __name__ == "__main__":
# 创建原型对象
prototype = Resume("张三", 25, "本科")
# 克隆对象
resume1 = prototype.clone()
resume2 = prototype.clone()
# 修改克隆对象
resume1.name = "张三-应聘Java开发"
resume2.name = "张三-应聘Python开发"
print("原型:", prototype)
print("克隆1:", resume1)
print("克隆2:", resume2)
🏗️ 架构级应用
把原型模式的思想从"克隆对象"放大到"克隆系统",就变成了架构层面的虚拟化技术。
-
虚拟机克隆:从一个虚拟机模板克隆出多个相同的虚拟机
-
容器镜像:从一个Docker镜像创建多个相同的容器
-
数据库备份恢复:从一个数据库备份恢复出多个相同的数据库
-
配置模板:从一个配置模板生成多个相同的配置文件
🏭 工业级中间件案例
-
Java Cloneable接口:Java提供的原型模式支持
-
C# MemberwiseClone方法:C#提供的原型模式支持
-
Python copy模块:Python提供的浅拷贝和深拷贝支持
-
Docker:容器化技术,基于镜像创建容器
-
VMware/VirtualBox:虚拟机软件,支持虚拟机克隆
⚠️ 实战优化避坑(三语完整实现)
坑点1:浅拷贝与深拷贝问题
问题:浅拷贝只会拷贝基本类型,不会拷贝引用类型,导致多个对象共享同一个引用对象
解决方案:使用深拷贝,递归拷贝所有引用类型的对象
// Java 深拷贝实现
class Resume implements Prototype {
private String name;
private int age;
private List<String> skills; // 引用类型
// 深拷贝
@Override
public Prototype clone() {
try {
Resume clone = (Resume) super.clone();
// 深拷贝引用类型
clone.skills = new ArrayList<>(this.skills);
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
坑点2:克隆对象的构造函数不会执行
问题:克隆对象是直接复制内存中的对象,不会执行构造函数
解决方案:如果需要执行初始化逻辑,可以在clone()方法中手动调用
坑点3:单例模式与原型模式冲突
问题:如果单例类实现了Cloneable接口,克隆会破坏单例
解决方案:单例类不要实现Cloneable接口,或者在clone()方法中抛出异常
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心一要素:原型接口(实现克隆方法) |
| 架构级 | 虚拟机克隆、容器镜像、数据库备份恢复、配置模板 |
| 工业级 | Java Cloneable、Docker、VMware、Python copy模块 |
第23章 解释器模式(Interpreter)- 行为型
核心一句话:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
🏠 生活真实故事
你去国外旅游,需要和当地人交流:
-
你说中文,当地人说英文
-
你需要一个翻译官
-
翻译官懂中文和英文两种语言
-
你说一句中文,翻译官翻译成英文告诉当地人
-
当地人说一句英文,翻译官翻译成中文告诉你
在这里,翻译官就是一个解释器:
-
他定义了中文和英文之间的转换规则
-
他可以解释(翻译)任何符合语法的中文或英文句子
📚 文科类比
-
翻译官:翻译不同语言之间的句子
-
乐谱:音乐家可以解释乐谱,演奏出音乐
-
密码本:特工可以解释密码,获取情报
-
交通标志:司机可以解释交通标志,知道该怎么做
💻 代码级:GoF 经典实现(三语标准)
Java 经典实现
// ============== 抽象表达式 ==============
interface Expression {
int interpret(Context context);
}
// ============== 终结符表达式:数字 ==============
class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Context context) {
return number;
}
}
// ============== 非终结符表达式:加法 ==============
class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}
// ============== 非终结符表达式:减法 ==============
class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
// ============== 上下文 ==============
class Context {
// 可以存储解释器需要的全局信息
}
// ============== 解释器 ==============
class Calculator {
public static int calculate(String expression) {
Stack<Expression> stack = new Stack<>();
String[] tokens = expression.split(" ");
for (int i = 0; i < tokens.length; i++) {
if (tokens[i].equals("+")) {
Expression left = stack.pop();
Expression right = new NumberExpression(Integer.parseInt(tokens[++i]));
stack.push(new AddExpression(left, right));
} else if (tokens[i].equals("-")) {
Expression left = stack.pop();
Expression right = new NumberExpression(Integer.parseInt(tokens[++i]));
stack.push(new SubtractExpression(left, right));
} else {
stack.push(new NumberExpression(Integer.parseInt(tokens[i])));
}
}
return stack.pop().interpret(new Context());
}
}
// ============== 测试类 ==============
public class InterpreterTest {
public static void main(String[] args) {
String expression = "1 + 2 + 3 - 4";
int result = Calculator.calculate(expression);
System.out.println(expression + " = " + result); // 输出:1 + 2 + 3 - 4 = 2
}
}
C# 经典实现
// ============== 抽象表达式 ==============
public interface IExpression
{
int Interpret(Context context);
}
// ============== 终结符表达式:数字 ==============
public class NumberExpression : IExpression
{
private int _number;
public NumberExpression(int number)
{
_number = number;
}
public int Interpret(Context context)
{
return _number;
}
}
// ============== 非终结符表达式:加法 ==============
public class AddExpression : IExpression
{
private IExpression _left;
private IExpression _right;
public AddExpression(IExpression left, IExpression right)
{
_left = left;
_right = right;
}
public int Interpret(Context context)
{
return _left.Interpret(context) + _right.Interpret(context);
}
}
// ============== 非终结符表达式:减法 ==============
public class SubtractExpression : IExpression
{
private IExpression _left;
private IExpression _right;
public SubtractExpression(IExpression left, IExpression right)
{
_left = left;
_right = right;
}
public int Interpret(Context context)
{
return _left.Interpret(context) - _right.Interpret(context);
}
}
// ============== 上下文 ==============
public class Context
{
// 可以存储解释器需要的全局信息
}
// ============== 解释器 ==============
public class Calculator
{
public static int Calculate(string expression)
{
Stack<IExpression> stack = new Stack<IExpression>();
string[] tokens = expression.Split(' ');
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i] == "+")
{
IExpression left = stack.Pop();
IExpression right = new NumberExpression(int.Parse(tokens[++i]));
stack.Push(new AddExpression(left, right));
}
else if (tokens[i] == "-")
{
IExpression left = stack.Pop();
IExpression right = new NumberExpression(int.Parse(tokens[++i]));
stack.Push(new SubtractExpression(left, right));
}
else
{
stack.Push(new NumberExpression(int.Parse(tokens[i])));
}
}
return stack.Pop().Interpret(new Context());
}
}
// ============== 测试类 ==============
public class InterpreterTest
{
public static void Main()
{
string expression = "1 + 2 + 3 - 4";
int result = Calculator.Calculate(expression);
Console.WriteLine(expression + " = " + result); // 输出:1 + 2 + 3 - 4 = 2
}
}
Python 经典实现
from abc import ABC, abstractmethod
# ============== 抽象表达式 ==============
class Expression(ABC):
@abstractmethod
def interpret(self, context):
pass
# ============== 终结符表达式:数字 ==============
class NumberExpression(Expression):
def __init__(self, number):
self.number = number
def interpret(self, context):
return self.number
# ============== 非终结符表达式:加法 ==============
class AddExpression(Expression):
def __init__(self, left, right):
self.left = left
self.right = right
def interpret(self, context):
return self.left.interpret(context) + self.right.interpret(context)
# ============== 非终结符表达式:减法 ==============
class SubtractExpression(Expression):
def __init__(self, left, right):
self.left = left
self.right = right
def interpret(self, context):
return self.left.interpret(context) - self.right.interpret(context)
# ============== 上下文 ==============
class Context:
pass
# ============== 解释器 ==============
class Calculator:
@staticmethod
def calculate(expression):
stack = []
tokens = expression.split()
i = 0
while i < len(tokens):
if tokens[i] == "+":
left = stack.pop()
right = NumberExpression(int(tokens[i+1]))
stack.append(AddExpression(left, right))
i += 2
elif tokens[i] == "-":
left = stack.pop()
right = NumberExpression(int(tokens[i+1]))
stack.append(SubtractExpression(left, right))
i += 2
else:
stack.append(NumberExpression(int(tokens[i])))
i += 1
return stack.pop().interpret(Context())
# ============== 测试代码 ==============
if __name__ == "__main__":
expression = "1 + 2 + 3 - 4"
result = Calculator.calculate(expression)
print(f"{expression} = {result}") # 输出:1 + 2 + 3 - 4 = 2
🏗️ 架构级应用
把解释器模式的思想从"解释简单表达式"放大到"解释复杂语言",就变成了架构层面的编译器/解释器。
-
SQL解析器:解析SQL语句,生成执行计划
-
正则表达式引擎:解析正则表达式,匹配字符串
-
模板引擎:解析模板语言,生成HTML页面
-
规则引擎:解析业务规则,执行相应的操作
🏭 工业级中间件案例
-
MySQL/Oracle:数据库的SQL解析器
-
Java编译器:将Java源代码编译成字节码
-
Python解释器:解释执行Python代码
-
ANTLR:语法分析器生成器,用于构建各种语言的解释器
-
Thymeleaf/Freemarker:模板引擎,解析模板语言
⚠️ 实战优化避坑(三语完整实现)
坑点1:只适合简单文法
问题:解释器模式只适合简单的文法,对于复杂的文法会产生大量的表达式类
解决方案:对于复杂的文法,使用ANTLR等专业的语法分析工具
坑点2:效率问题
问题:解释器模式使用递归调用,对于复杂的表达式效率较低
解决方案:将表达式编译成字节码或机器码,提高执行效率
坑点3:维护困难
问题:文法的变化会导致所有表达式类的变化,维护困难
解决方案:只有当文法相对稳定时,才使用解释器模式
📝 本课总结
| 层级 | 核心体现 |
|---|---|
| 代码级 | 核心二要素:抽象表达式、终结符/非终结符表达式 |
| 架构级 | SQL解析器、正则表达式引擎、模板引擎、规则引擎 |
| 工业级 | MySQL SQL解析器、Java编译器、Python解释器、ANTLR |
附录
附录:23个设计模式完整速查表
📖 本速查表的详细版本(含6大思维分组、跨学科原理对应、学习路线与建议)已迁移至续集《设计模式公理化推演体系》中。
| 模式名称 | 类别 | 核心一句话 |
|---|---|---|
| 单例模式 | 创建型 | 全局唯一实例,统一访问入口 |
| 工厂方法模式 | 创建型 | 把对象创建交给子类,创建与使用分离 |
| 抽象工厂模式 | 创建型 | 创建一组相关的对象,保证产品族一致性 |
| 建造者模式 | 创建型 | 构建复杂对象,分离构建与表示 |
| 原型模式 | 创建型 | 克隆对象,避免重复创建 |
| 代理模式 | 结构型 | 为其他对象提供代理以控制访问 |
| 外观模式 | 结构型 | 为复杂子系统提供统一入口 |
| 适配器模式 | 结构型 | 转换接口,解决不兼容问题 |
| 桥接模式 | 结构型 | 分离抽象与实现,解决多维度变化导致的类爆炸 |
| 组合模式 | 结构型 | 统一处理树形结构中的单个对象和组合对象 |
| 装饰器模式 | 结构型 | 动态叠加功能,替代继承 |
| 享元模式 | 结构型 | 共享细粒度对象,减少内存占用 |
| 策略模式 | 行为型 | 同一目标,多种算法,动态切换 |
| 模板方法模式 | 行为型 | 定义算法骨架,子类实现特定步骤 |
| 观察者模式 | 行为型 | 一对多订阅-发布,状态变更自动通知 |
| 迭代器模式 | 行为型 | 提供统一的方式遍历集合,不暴露内部结构 |
| 责任链模式 | 行为型 | 请求沿链传递,直到被处理 |
| 命令模式 | 行为型 | 封装请求为对象,支持撤销/排队 |
| 状态模式 | 行为型 | 状态改变时改变行为,消灭if-else |
| 中介者模式 | 行为型 | 用中介对象封装对象交互,减少耦合 |
| 访问者模式 | 行为型 | 稳定数据结构下的新操作,开闭原则极限 |
| 备忘录模式 | 行为型 | 保存和恢复对象状态,实现撤销/存档 |
| 解释器模式 | 行为型 | 定义语言文法并解释执行 |
🎉 恭喜!你已经学完了GoF 23个经典设计模式!
学习建议:
- 先掌握前5个最常用的模式:单例、工厂方法、策略、观察者、装饰器
- 再掌握中间8个常用模式:代理、外观、模板方法、适配器、建造者、责任链、命令、状态
- 最后了解剩下10个不常用模式,知道它们的适用场景即可
- 最重要的是在实际项目中多运用,才能真正理解设计模式的精髓
📖 续集推荐:《设计模式公理化推演体系》—— 从公理到范式的演绎之旅
更多推荐




所有评论(0)