首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 建構子設計原則:不要在建構子直接讀取用戶輸入

     編輯:程式設計疑難解答

問題:需透過用戶輸入建立物件,建構子該怎麼寫?

反模式:建構子內直接 `Scanner` 讀取


// 不推薦
public class User {
    String name;
    public User() {
        Scanner sc = new Scanner(System.in);
        System.out.print("輸入姓名: ");
        this.name = sc.nextLine(); // 測試困難、耦合標準輸入、異常處理混雜
    }
}

推薦模式:建構子接受參數,呼叫端負責取得輸入


// 推薦
public class User {
    private final String name;
    public User(String name) { this.name = name; } // 純初始化
    public String getName() { return name; }
}

// 呼叫端 (Controller / Main / Service)
public class UserFactory {
    public static User createFromConsole() {
        Scanner sc = new Scanner(System.in);
        System.out.print("輸入姓名: ");
        String name = sc.nextLine().trim();
        // 可在這裡驗證、預設值、重試邏輯
        return new User(name);
    }
}

優勢對照

維度建構子讀輸入參數化建構子 + Factory
可測試性難 (需模擬 System.in)易 (直接 `new User("Alice")`)
單一職責違反 (混雜 I/O 與初始化)符合 (建構子只初始化)
不可變性難保證易用 `final` 欄位保證
異常處理建構子拋異常 → 物件半初始化Factory 回傳 `Optional` 或拋出具體異常
重用性僅限 Console支援 GUI、Web、檔案、測試資料等多來源

替代方案:Builder 模式 (參數多時)


public class User {
    private final String name;
    private final int age;
    private final String email;
    private User(Builder b) { this.name=b.name; this.age=b.age; this.email=b.email; }
    public static class Builder {
        String name; int age; String email;
        Builder name(String v){name=v;return this;}
        Builder age(int v){age=v;return this;}
        Builder email(String v){email=v;return this;}
        User build(){ return new User(this); }
    }
}
// 使用
User u = new User.Builder().name("Bob").age(25).email("bob@ex.com").build();

總結原則

  1. **建構子只負責將參數賦值給欄位**,不做 I/O、不做複雜運算、不拋受檢異常。
  2. 輸入取得、驗證、轉換 → **Factory / Builder / Service 層**處理。
  3. 欄位盡量 `final`,確保物件建立後狀態不可變、線程安全。

遵循「建構子純初始化」原則,代碼即獲得高可測試性、低耦合、易維護三大優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved