手機是隨身數位終端,記錄碎片資訊是剛需。Note 專案目標:單機版記事本,支援新增、瀏覽、編輯、刪除、重命名,採用 MVC 嚴格分層,驗證架構在資源受限平台的落地可行性。
事件流圖(省略)已轉化為循序圖,驅動類別發現。
| 層級 | 類別(命名慣例) | 職責 |
|---|---|---|
| Model (Entity) | Note | 資料實體:id、title、content、datetime;getter/setter、序列化 |
NoteLocator | 生命週期管理:RMS 持久化、查詢、快取、單例模式 | |
| Controller (Workflow) | NoteManagerWorkflow | 管理用例控制:列表資料準備、刪除協調、ID/Title 雙陣列維護 |
NoteEditWorkflow | 編輯用例控制:載入/儲存/另存邏輯、惰性初始化 Note 實體 | |
NotepadWorkflow | 瀏覽用例控制:資料轉換、轉向編輯流程 | |
| View (Boundary/UI) | NoteManagerUI | 列表畫面:List 元件、命令處理、向 Workflow 索取 String[] |
NoteEditUI | 編輯畫面:Form + TextField、儲存/另存命令、回調 Workflow | |
NotepadUI | 瀏覽畫面:顯示完整內容、編輯/返回命令 |
// NoteManagerUI 完全不曉得 RMS、Note 物件結構
public interface NoteManagerDataProvider {
String[] getTitleList(); // 供 List 顯示
String[] getIdList(); // 內部識別用,不顯示
void deleteNote(int index); // 委派刪除
}
NoteManagerUI 持有 NoteManagerDataProvider 介面參考,實作類為 NoteManagerWorkflow。編譯期依賴倒置,UI 層零業務邏輯。
public class NoteManagerWorkflow implements NoteManagerDataProvider {
private NoteLocator locator = NoteLocator.getInstance(); // 單例
private String[] titleCache, idCache;
public String[] getTitleList() {
if (titleCache == null) refreshCache();
return titleCache;
}
private void refreshCache() {
Vector notes = locator.findAllNotes(); // 從 RMS 載入
titleCache = new String[notes.size()];
idCache = new String[notes.size()];
for (int i=0;i locator.deleteNote(idCache[index]) -> refreshCache()
}
public class NotepadWorkflow {
private Note note; // 實體引用
private String noteId;
public Note getNote() { // 供 UI 呼叫取資料
if (note == null && noteId != null) {
note = NoteLocator.getInstance().findById(noteId); // 首次載入
}
return note;
}
// UI 呼叫 getNote().getTitle() 等,無需知悉載入細節
}
避免預載入大量 Note 物件佔用堆疊,按需載入、按需釋放。


啟動 → Manager列表 → (新增/選中) → Edit/Notepad → 儲存/返回 → Manager 刷新
![]() Manager 列表 |
![]() Edit 新建 |
![]() 儲存輸入標題 |
![]() 列表更新 |
![]() Notepad 瀏覽 |
// BaseView.java
public abstract class BaseView {
public abstract Display getDisplay();
public abstract Displayable getScreen();
protected abstract void createView() throws Exception;
public abstract void updateView() throws Exception;
public abstract BaseController getController();
public Displayable prepareScreen() throws Exception {
if (getScreen() == null) createView(); else updateView();
return getScreen();
}
public void displayScreen() {
try { getDisplay().setCurrent(prepareScreen()); }
catch (Exception e) { showError(e); }
}
}
// BaseController.java
public abstract class BaseController {
public abstract BaseView getView();
public abstract void setView(BaseView view);
}
構造時雙向綁定:controller.setView(view); view.getController() == controller,避免 NPE。
Note 專案證明:MVC 在 J2ME 不僅可行,更是中型以上專案的必然選擇。嚴格分層讓 RMS 操作、UI 邏輯、業務流程各自可測、可替換。代碼雖多,但結構清晰,新成員閱讀 BaseView/BaseController 即可掌握全專案協作規範。這正是「架構服務於人」的最佳註腳。