是否应将HashMap管理方法移至独立静态类?Java架构实践问询
绝对应该迁移!这是符合单一职责原则的良好编程实践
首先给你一个明确的答案:把操作索引卡片集合的静态方法移到单独的ListAdministrator类,不仅合理,而且是非常值得推荐的面向对象设计实践。核心原因是这完美遵循了单一职责原则——每个类只专注于一件事:
IndexCard只需要管好自己:表示单张索引卡片的属性,以及只和自身相关的操作(比如更新自己的信息、删除自己、打印自己的内容)ListAdministrator专门负责管好所有卡片的集合:处理查找、批量展示、集合维护这类和整体列表相关的逻辑
这么做的核心好处:
- 代码可读性拉满:其他开发者一看类名就知道该找什么逻辑,不用在
IndexCard里既找单张卡片的属性,又找批量搜索的代码 - 降低耦合度:原来
IndexCard和静态集合绑定死了,现在集合的实现(比如以后要换成线程安全的ConcurrentHashMap)只需要改ListAdministrator,完全不影响IndexCard的代码 - 测试更方便:单独的管理类更容易写单元测试,比如测试搜索功能,不用先创建一堆
IndexCard实例 - 避免静态状态污染:原来
IndexCard里的静态list是类级别的全局状态,容易在多线程场景出问题,移到专门的类后,线程安全的处理逻辑可以更集中清晰
重构后的代码示例
我帮你把代码做了规范的重构,同时修正了一些小细节(比如原代码里关闭Scanner会导致后续无法读取输入的问题):
重构后的IndexCard类
import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.time.LocalDate; import java.util.Scanner; class IndexCard { public String name; public String address; public String phone; public String email; public LocalDate dateRegister; IndexCard(String name, String dni, String address, String phone, String email) { this.name = name; this.address = address; this.phone = phone; this.email = email; dateRegister = LocalDate.now(); if (Utils.validarDni(dni) && !ListAdministrator.getList().containsKey(dni)) { ListAdministrator.addCard(dni, this); } else { throw new InvalidParameterException("Error when entering the data or the DNI has already been previously registered"); } } /** * Update the data of the selected card. */ public void update() throws IllegalAccessException { String key = ListAdministrator.getKeyWithObject(this); Scanner reader = new Scanner(System.in); Field[] fields = this.getClass().getFields(); for (Field field : fields) { String nameField = Utils.splitCamelCase(field.getName()); if (!Modifier.isStatic(field.getModifiers()) && field.getType().equals(String.class)) { System.out.println("Enter new " + nameField); String value = reader.nextLine().trim(); field.set(this, value); } } // 注意:不要关闭System.in的Scanner,否则后续无法再读取输入 ListAdministrator.addCard(key, this); System.out.println("Updated data \n \n"); } /** * Delete the selected card. */ public void delete() throws IllegalAccessException { String key = ListAdministrator.getKeyWithObject(this); Field[] fields = this.getClass().getFields(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { field.set(this, null); } } ListAdministrator.getList().remove(key); } /** * Displays the data of the selected card on screen. */ public void print() throws IllegalAccessException { Field[] fields = this.getClass().getFields(); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { String nameFieldConSpaces = Utils.splitCamelCase(field.getName()); Object value = field.get(this); System.out.println(nameFieldConSpaces + ":" + value); } } } }
重构后的ListAdministrator类
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; class ListAdministrator { // 设为private,通过公共方法访问,防止外部直接篡改集合 private static final HashMap<String, IndexCard> list = new HashMap<>(); /** * Print all entries of the desired subclass with ID, Name and Phone */ public static <T extends IndexCard> void printSubClassList(Class<T> subClass) { for (Map.Entry<String, IndexCard> entry : list.entrySet()) { String key = entry.getKey(); IndexCard card = entry.getValue(); if (card.getClass().equals(subClass)) { System.out.println("ID:" + key + "| Name:" + card.name + "| Phone:" + card.phone); } } } /** * Get card by its key (DNI) */ public static IndexCard getObjectWithKey(String key) { try { return list.get(key); } catch (IllegalArgumentException e) { System.out.println(e + ": The indicated key does not appear in the database."); return null; } } /** * Get the key (DNI) associated with a card */ public static String getKeyWithObject(Object obj) { for (Map.Entry<String, IndexCard> entry : list.entrySet()) { if (obj.equals(entry.getValue())) { return entry.getKey(); } } throw new IllegalArgumentException("The indicated data does not appear in the database, and therefore we could not obtain the key."); } /** * Search cards by name (case-insensitive) */ public static ArrayList<IndexCard> searchByName(String data) { try { ArrayList<IndexCard> listCards = new ArrayList<>(); String lowerCaseQuery = data.toLowerCase().trim(); for (Map.Entry<String, IndexCard> entry : list.entrySet()) { IndexCard card = entry.getValue(); if (card.name.toLowerCase().trim().contains(lowerCaseQuery)) { listCards.add(card); } } return listCards; } catch (IllegalArgumentException e) { System.out.println(e + "The indicated data does not appear in the database, you may have entered it incorrectly."); return null; } } // 提供安全的集合访问方法(返回不可修改视图) public static Map<String, IndexCard> getList() { return Map.copyOf(list); } // 新增add方法,封装集合添加逻辑 public static void addCard(String dni, IndexCard card) { if (!list.containsKey(dni)) { list.put(dni, card); } } }
额外的优化建议
- 保持
ListAdministrator的list为private,通过封装的方法操作集合,避免外部直接修改,保证数据一致性 - 严格遵循Java命名规范:方法名用小驼峰(比如原
GetObjetWithKey改成getObjectWithKey) - 如果未来可能需要多个索引卡片列表(比如不同分类的卡片),可以把
ListAdministrator改成非静态类,用单例模式或者依赖注入管理实例,扩展性会更好
内容的提问来源于stack exchange,提问作者juan fran
相关产品推荐
相关产品推荐

