ControlPoints 類別是應用程式的模型層核心,負責封裝 LandmarkStore 的操作,提供地標的新增、查詢、更新與刪除功能。它採用單例模式設計,確保全域只有一個實例存取持久化的地標資料庫。
首先建立 ControlPoints.java,並匯入 JSR-179 相關套件以及 Java 基礎 I/O 與集合類別:
package com.nokia.example.location.tourist.model;
import java.io.IOException;
import java.util.Enumeration;
import javax.microedition.location.Coordinates;
import javax.microedition.location.Landmark;
import javax.microedition.location.LandmarkException;
import javax.microedition.location.LandmarkStore;
類別定義地標儲存庫名稱、預設分類與單例實例變數:
public class ControlPoints {
private LandmarkStore store = null;
private static final String STORENAME = "TOURIST_DEMO";
private static final String DEFAULT_CATEGORY = null;
private static ControlPoints INSTANCE = null;
// ...
建構子嘗試取得名為 TOURIST_DEMO 的儲存庫;若不存在則建立新儲存庫,並處理可能發生的 IOException、LandmarkException 等異常:
private ControlPoints() {
String name = null;
try {
store = LandmarkStore.getInstance(STORENAME);
} catch (NullPointerException npe) {
// 理論上不會發生
}
if (store == null) {
try {
LandmarkStore.createLandmarkStore(STORENAME);
name = STORENAME;
} catch (IllegalArgumentException iae) {
// 名稱過長或已存在
} catch (IOException e) {
// I/O 錯誤
} catch (LandmarkException e) {
// 不支援建立新儲存庫
}
store = LandmarkStore.getInstance(name);
}
}
標準的單例 getInstance() 方法:
public static ControlPoints getInstance() {
if (INSTANCE == null) {
INSTANCE = new ControlPoints();
}
return INSTANCE;
}
public Landmark findLandmark(int index) {
Landmark lm = null;
Enumeration cps = getLandMarks();
int counter = 0;
while (cps.hasMoreElements()) {
lm = (Landmark) cps.nextElement();
if (counter == index) break;
counter++;
}
return lm;
}
public Enumeration getLandMarks() {
Enumeration enu = null;
try {
enu = store.getLandmarks();
} catch (IOException ioe) {
// 存取儲存庫發生 I/O 錯誤
}
return enu;
}
給定座標,在半徑 0.1 度範圍內搜尋最近的地標:
public Landmark findNearestLandMark(Coordinates coord) {
Landmark landmark = null;
double latRadius = 0.1, lonRadius = 0.1;
float dist = Float.MAX_VALUE;
try {
Enumeration enu = store.getLandmarks(null,
coord.getLatitude() - latRadius, coord.getLatitude() + latRadius,
coord.getLongitude() - lonRadius, coord.getLongitude() + lonRadius);
while (enu.hasMoreElements()) {
Landmark tmpLandmark = (Landmark) enu.nextElement();
float tmpDist = tmpLandmark.getQualifiedCoordinates().distance(coord);
if (tmpDist < dist) {
landmark = tmpLandmark;
dist = tmpDist;
}
}
} catch (IOException ioe) {
return null;
}
return landmark;
}
public void addLandmark(Landmark landmark) throws IOException {
store.addLandmark(landmark, DEFAULT_CATEGORY);
}
public void updateLandmark(Landmark landmark) throws IOException, LandmarkException {
store.updateLandmark(landmark);
}
public void removeLandmark(Landmark landmark) throws IOException, LandmarkException {
store.deleteLandmark(landmark);
}
}
小結: ControlPoints 封裝了所有地標持久化操作,上層 UI 僅需呼叫單例方法即可完成資料存取,達到關注點分離。