雖然狀態模式與策略模式在 UML 結構上極度相似,皆遵循開閉原則,但意圖截然不同:
| 維度 | 策略模式 | 狀態模式 |
|---|---|---|
| 封裝對象 | 算法/策略 | 對象狀態 |
| 狀態轉移驅動者 | 客戶端主動設定 | Context 或 State 內部管理 |
| 持有 Context 引用 | 否 | 是(用於狀態轉換) |
| 可復用性 | 高(獨立於上下文) | 低(與對象強耦合) |
| 核心關注 | 「如何做」(How) | 「什麼時候做什麼」(What & When) |
| 單一職責原則 | 符合 | 視實現而定 |
// 狀態介面
public interface State {
void handle(Context ctx);
}
// 具體狀態:視窗模式
public class WindowState implements State {
private String value;
public WindowState(String v) { value = v; }
public void handle(Context ctx) {
if ("窗口".equals(value)) {
System.out.println("切換為全屏模式");
ctx.setState(new WindowState("全屏"));
} else {
System.out.println("切換為窗口模式");
ctx.setState(new WindowState("窗口"));
}
}
}
// 上下文管理狀態
public class Context {
private State state;
public Context(State s) { state = s; }
public void setState(State s) { state = s; }
public void request() { state.handle(this); }
}
// 策略介面:收費算法
public interface CashStrategy {
double acceptCash(double money);
}
// 正常收費
public class CashNormal implements CashStrategy {
public double acceptCash(double m) { return m; }
}
// 打折策略
public class CashRebate implements CashStrategy {
private double rebate;
public CashRebate(double r) { rebate = r; }
public double acceptCash(double m) { return m * rebate / 10; }
}
// 滿減策略
public class CashReturn implements CashStrategy {
private double condition, returnMoney;
public CashReturn(double c, double r) { condition = c; returnMoney = r; }
public double acceptCash(double m) {
return m >= condition ? m - (int)(m/condition)*returnMoney : m;
}
}
// 上下文使用策略
public class CashContext {
private CashStrategy strategy;
public void setStrategy(CashStrategy s) { strategy = s; }
public double getResult(double money) { return strategy.acceptCash(money); }
}