本文展示用戶模組的完整分層實作:值物件 (VO)、枚舉、DAO 層 (檔案儲存)、業務邏輯層 (EBI/EBO)、工廠模式,並整合通用 UUID 生成機制。
package cn.hncu.bookStore.user.vo;
import java.io.Serializable;
import cn.hncu.bookStore.user.common.UserTypeEnum;
public class UserModel implements Serializable {
private static final long serialVersionUID = 1L;
private String uuid; // 主鍵 (UUID 生成)
private String name; // 用戶名
private String pwd; // 密碼 (實務應加密儲存)
private int type; // 權限類型 (參照 UserTypeEnum)
// Getter/Setter 省略...
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
UserModel other = (UserModel) obj;
return uuid != null ? uuid.equals(other.uuid) : other.uuid == null;
}
@Override
public int hashCode() {
return uuid == null ? 0 : uuid.hashCode();
}
@Override
public String toString() {
return uuid + "," + name + "," + UserTypeEnum.getNameByType(type);
}
}
// 查詢條件模型 (繼承 UserModel 復用欄位)
public class UserQueryModel extends UserModel {
private static final long serialVersionUID = 1L;
// 可擴充額外查詢條件 (如日期範圍)
}
package cn.hncu.bookStore.user.common;
public enum UserTypeEnum {
ADMIN(1, "超級管理員"),
BOOK(2, "圖書管理員"),
IN(3, "進貨管理員"),
OUT(4, "銷售管理員"),
STOCK(5, "庫存管理員");
private final int type;
private final String name;
UserTypeEnum(int type, String name) { this.type = type; this.name = name; }
public int getType() { return type; }
public String getName() { return name; }
// 反向查找:名稱 → 類型碼
public static int getTypeByName(String name) {
for (UserTypeEnum e : values()) {
if (e.name.equalsIgnoreCase(name.trim())) return e.type;
}
throw new IllegalArgumentException("無效用戶類型: " + name);
}
// 反向查找:類型碼 → 名稱
public static String getNameByType(int type) {
for (UserTypeEnum e : values()) {
if (e.type == type) return e.name;
}
throw new IllegalArgumentException("無效類型碼: " + type);
}
}
package cn.hncu.bookStore.user.dao.dao;
import java.util.List;
import cn.hncu.bookStore.user.vo.UserModel;
import cn.hncu.bookStore.user.vo.UserQueryModel;
public interface UserDAO {
boolean create(UserModel user);
boolean delete(String uuid);
boolean update(UserModel user);
UserModel getSingle(String uuid);
List getByCondition(UserQueryModel user);
List getAll();
}
package cn.hncu.bookStore.user.dao.impl;
import java.util.ArrayList;
import java.util.List;
import cn.hncu.bookStore.user.dao.dao.UserDAO;
import cn.hncu.bookStore.user.vo.UserModel;
import cn.hncu.bookStore.user.vo.UserQueryModel;
import cn.hncu.bookStore.utils.FileIOUtil;
public class UserDAOFileImpl implements UserDAO {
private static final String FILE_NAME = "user.dat"; // 序列化檔案
@Override
public boolean create(UserModel user) {
if (user == null) return false;
List list = getAll();
for (UserModel u : list) {
if (u.getUuid().equals(user.getUuid())) return false; // UUID 重複
}
list.add(user);
return FileIOUtil.writeToFile(list, FILE_NAME);
}
@Override
public boolean delete(String uuid) {
List list = getAll();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getUuid().equals(uuid)) {
list.remove(i);
return FileIOUtil.writeToFile(list, FILE_NAME);
}
}
return false;
}
@Override
public boolean update(UserModel user) {
List list = getAll();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getUuid().equals(user.getUuid())) {
list.set(i, user);
return FileIOUtil.writeToFile(list, FILE_NAME);
}
}
return false;
}
@Override
public UserModel getSingle(String uuid) {
for (UserModel u : getAll()) {
if (u.getUuid().equals(uuid)) return u;
}
return null;
}
@Override
public List getByCondition(UserQueryModel q) {
List all = getAll();
List result = new ArrayList<>();
for (UserModel u : all) {
if (q.getUuid() != null && !q.getUuid().trim().isEmpty()
&& !q.getUuid().equals(u.getUuid())) continue;
if (q.getName() != null && !q.getName().trim().isEmpty()
&& u.getName().indexOf(q.getName()) == -1) continue;
if (q.getType() > 0 && u.getType() != q.getType()) continue;
result.add(u);
}
return result;
}
@Override
public List getAll() {
return FileIOUtil.readFromFile(FILE_NAME);
}
}
package cn.hncu.bookStore.user.dao.factory;
import cn.hncu.bookStore.user.dao.dao.UserDAO;
import cn.hncu.bookStore.user.dao.impl.UserDAOFileImpl;
public class UserDAOFactory {
private UserDAOFactory() {}
public static UserDAO getUserDAO() {
return new UserDAOFileImpl();
}
}
package cn.hncu.bookStore.user.business.ebi;
import java.util.List;
import cn.hncu.bookStore.user.vo.UserModel;
import cn.hncu.bookStore.user.vo.UserQueryModel;
public interface UserEBI {
boolean create(UserModel user);
boolean delete(String uuid);
boolean update(UserModel user);
UserModel getSingle(String uuid);
List getByCondition(UserQueryModel user);
List getAll();
// 業務專用查詢
List getAllIn(); // 取得所有進貨管理員
List getAllOut(); // 取得所有銷售管理員
}
package cn.hncu.bookStore.user.business.ebo;
import java.util.List;
import cn.hncu.bookStore.common.uuidModelConstance;
import cn.hncu.bookStore.common.uuid.dao.factory.UUIDDAOFactory;
import cn.hncu.bookStore.user.business.ebi.UserEBI;
import cn.hncu.bookStore.user.common.UserTypeEnum;
import cn.hncu.bookStore.user.dao.dao.UserDAO;
import cn.hncu.bookStore.user.dao.factory.UserDAOFactory;
import cn.hncu.bookStore.user.vo.UserModel;
import cn.hncu.bookStore.user.vo.UserQueryModel;
public class UserEBO implements UserEBI {
private UserDAO dao = UserDAOFactory.getUserDAO();
@Override
public boolean create(UserModel user) {
// 1. 自動生成 UUID
String uuid = UUIDDAOFactory.getUUIDDAO().getNextNum(UUIDModelConstance.USER);
user.setUuid(uuid);
// 2. 委派 DAO 持久化
return dao.create(user);
}
@Override
public boolean delete(String uuid) {
return dao.delete(uuid);
}
@Override
public boolean update(UserModel user) {
return dao.update(user);
}
@Override
public UserModel getSingle(String uuid) {
return dao.getSingle(uuid);
}
@Override
public List getByCondition(UserQueryModel user) {
return dao.getByCondition(user);
}
@Override
public List getAll() {
return dao.getAll();
}
@Override
public List getAllIn() {
UserQueryModel q = new UserQueryModel();
q.setType(UserTypeEnum.IN.getType());
return dao.getByCondition(q);
}
@Override
public List getAllOut() {
UserQueryModel q = new UserQueryModel();
q.setType(UserTypeEnum.OUT.getType());
return dao.getByCondition(q);
}
}
package cn.hncu.bookStore.user.business.factory;
import cn.hncu.bookStore.user.business.ebi.UserEBI;
import cn.hncu.bookStore.user.business.ebo.UserEBO;
public class UserEBIFactory {
private UserEBIFactory() {}
public static UserEBI getUserEBI() {
return new UserEBO();
}
}
| 設計點 | 實作方式 | 效益 |
|---|---|---|
| UUID 統一生成 | UUIDDAO + 檔案計數器 | 跨實體唯一、無需資料庫自增、可移植 |
| 枚舉驅動權限 | UserTypeEnum + 反向查找 | 類型安全、前後端一致、易擴充 |
| 查詢模型繼承 | UserQueryModel extends UserModel | 復用欄位定義、自動擁有所有查詢條件 |
| DAO 介面導向 | UserDAO + FileImpl + Factory | 測試可 Mock、未來換資料庫只改實作 |
| 業務層封裝 | EBI/EBO + Factory | 事務邊界、權限檢查、組合查詢集中管理 |
| 序列化持久化 | FileIOUtil (ObjectOutputStream) | 零配置、物件圖完整儲存、適合教學/小型應用 |
第三部分將展示 Swing UI 面板實作:listPanel (列表/操作入口)、AddPanel、UpdatePanel、DeletePanel、QueryPanel,以及事件處理與面板切換邏輯。