代碼疑惑
protected ButtonModel model = null;
public ButtonModel getModel() { return model; }
public void setActionCommand(String actionCommand) {
getModel().setActionCommand(actionCommand); // model 為 null,為何不 NPE?
}
真相:model 並非始終為 null
AbstractButton 構造器中會初始化 model:
public AbstractButton() {
model = new DefaultButtonModel(); // 具體實現類
}
子類(JButton、JToggleButton 等)繼承此構造器,**model 在對象構建完成前已被賦值為非 null 實例**。
設計模式:策略模式
- Context:
AbstractButton(委派行為給 Model)。
- Strategy 介面:
ButtonModel(定義狀態管理協議:armed、pressed、selected、actionCommand)。
- ConcreteStrategy:
DefaultButtonModel(標準實現)、ToggleButtonModel(單選/複選邏輯)。
- 客戶端:可運行時替換 Model 實現不同行為(如自定義模型實現特殊狀態機)。
為何用介面而非繼承?
| 繼承 | 策略模式(組合) |
| 靜態綁定,編譯期固定 | 動態替換,運行期靈活 |
| 單一繼承限制 | 可組合多種行為 |
| 子類爆炸 | 新增行為只需新增 Model 實現 |
源碼驗證路徑
- JDK 安裝目錄
src.zip → javax/swing/AbstractButton.java 第 150 行左右。
DefaultButtonModel.java 實現 setActionCommand 等方法。
自定義 Model 示例
public class LoggingButtonModel extends DefaultButtonModel {
@Override
public void setActionCommand(String cmd) {
System.out.println("ActionCommand changed: " + cmd);
super.setActionCommand(cmd);
}
}
// 使用
JButton btn = new JButton("Click");
btn.setModel(new LoggingButtonModel()); // 運行時替換
總結
model 初始為 null 只是聲明時的默認值,**構造器保證實例化前賦值非 null 實例**。這是教科書級策略模式應用:將按鈕狀態邏輯從 UI 組件中分離,實現高內聚、低耦合、可擴展設計。
- 上一篇文章: C# null != null 判斷失效實為邏輯寫反:RegEx.IsMatch 正確用法
- 下一篇文章: Android Ant 混淆打包 ProGuard 配置優化與警告消除
Copyright ©
程式碼之家 All Rights Reserved