2008-10-21 45 views
82

Trong một số dự án của chúng tôi, có một hệ thống phân cấp lớp bổ sung thêm các thông số khi nó đi xuống chuỗi. Ở phía dưới, một số lớp có thể có tối đa 30 tham số, 28 trong số đó chỉ được truyền vào hàm tạo siêu.Quản lý các hàm tạo với nhiều tham số trong Java

Tôi sẽ thừa nhận rằng việc sử dụng DI tự động thông qua một cái gì đó như Guice sẽ tốt đẹp, nhưng vì một số lý do kỹ thuật, các dự án cụ thể này bị ràng buộc với Java.

Quy ước sắp xếp đối số theo thứ tự bảng chữ cái không hoạt động vì nếu loại được tái cấu trúc (Vòng tròn bạn đã chuyển cho đối số 2 giờ là Hình dạng), nó có thể đột ngột bị hỏng.

Câu hỏi này có thể cụ thể và đầy "Nếu đó là vấn đề của bạn, bạn đang làm sai ở mức thiết kế" chỉ trích, nhưng tôi chỉ tìm kiếm bất kỳ quan điểm nào.

Trả lời

219

Các mẫu Builder Thiết kế có thể giúp đỡ. Hãy xem xét ví dụ sau

public class StudentBuilder 
{ 
    private String _name; 
    private int _age = 14;  // this has a default 
    private String _motto = ""; // most students don't have one 

    public StudentBuilder() { } 

    public Student buildStudent() 
    { 
     return new Student(_name, _age, _motto); 
    } 

    public StudentBuilder name(String _name) 
    { 
     this._name = _name; 
     return this; 
    } 

    public StudentBuilder age(int _age) 
    { 
     this._age = _age; 
     return this; 
    } 

    public StudentBuilder motto(String _motto) 
    { 
     this._motto = _motto; 
     return this; 
    } 
} 

Điều này cho phép chúng ta viết mã như

Student s1 = new StudentBuilder().name("Eli").buildStudent(); 
Student s2 = new StudentBuilder() 
       .name("Spicoli") 
       .age(16) 
       .motto("Aloha, Mr Hand") 
       .buildStudent(); 

Nếu chúng ta rời khỏi một trường bắt buộc (có lẽ tên là bắt buộc) sau đó chúng ta có thể có các nhà xây dựng Student ném một ngoại lệ. Và nó cho phép chúng tôi có đối số mặc định/tùy chọn mà không cần theo dõi bất kỳ loại thứ tự đối số nào, vì bất kỳ thứ tự nào của các cuộc gọi đó sẽ hoạt động tốt như nhau.

+8

Tất nhiên với nhập khẩu tĩnh bạn thậm chí không bao giờ phải "nhìn thấy" những "nhà xây dựng" ở tất cả. Ví dụ, bạn có thể có tên phương thức tĩnh (String name) trả về một trình tạo và Student (StudentBuilder) trả về một sinh viên. Do đó Học sinh (tên ("Joe"). Tuổi (15) .motto ("Tôi đã ướt bản thân mình")); –

+2

@oxbow_lakes: Trong ví dụ của bạn, lớp nào có tên phương thức tĩnh (Tên chuỗi)? – user443854

+0

Về mặt kỹ thuật, có thể sử dụng lớp Học sinh để xây dựng một học sinh mới. Tôi đã thêm các phương thức bên trong lớp Student và nó hoạt động tốt. Bằng cách này tôi không cần phải có một lớp xây dựng khác. Tôi không chắc chắn nếu điều này là mong muốn mặc dù. Có lý do nào để sử dụng lớp học khác (StudentBuilder) để xây dựng nó không? – WVrock

1

Tái cấu trúc để giảm số lượng tham số và chiều sâu của hệ thống phân cấp thừa kế của bạn là khá nhiều tất cả những gì tôi có thể nghĩ vì, không có gì thực sự giúp giữ thông số 20 cái gì đó thẳng. Bạn sẽ chỉ phải thực hiện mọi cuộc gọi trong khi xem tài liệu.

Một điều bạn có thể làm là nhóm một số tham số nhóm hợp lý vào đối tượng cấp cao hơn của riêng chúng, nhưng có vấn đề riêng.

3

Giải pháp tốt nhất không có quá nhiều tham số trong hàm tạo. Chỉ các tham số thực sự cần thiết trong hàm tạo, là các tham số cần phải khởi tạo chính xác đối tượng. Bạn có thể có các hàm tạo với nhiều tham số, nhưng cũng có một hàm tạo chỉ với các tham số tối thiểu. Các constructor bổ sung gọi hàm tạo đơn giản này và sau đó các bộ định cư để thiết lập các tham số khác. Bằng cách này, bạn có thể tránh được vấn đề chuỗi với nhiều thông số hơn, nhưng cũng có một số nhà xây dựng tiện lợi.

4

Khi bạn bị ràng buộc với Java 1.4, nếu bạn muốn DI thì Spring sẽ là một lựa chọn rất tốt. DI chỉ hữu ích ở những nơi mà các tham số của hàm tạo là các dịch vụ hoặc một thứ không thay đổi trong thời gian chạy.

Nếu bạn có tất cả các nhà xây dựng khác nhau do thực tế là bạn muốn tùy chọn biến về cách xây dựng một đối tượng, bạn nên cân nhắc nghiêm túc việc sử dụng mẫu Builder.

+0

Các tham số chủ yếu là các dịch vụ như bạn đã đề cập và vì vậy DI là những gì tôi cần. Tôi nghĩ rằng mô hình Builder được đề cập trong một vài câu trả lời khác là chính xác những gì tôi đã hy vọng. –

14

Điều bạn có thể muốn làm là có lớp Trình tạo. Sau đó, bạn sẽ làm điều gì đó như thế này:

MyObject obj = new MyObjectBuilder().setXxx(myXxx) 
            .setYyy(myYyy) 
            .setZzz(myZzz) 
            // ... etc. 
            .build(); 

Xem trang 8 và sau this Josh Bloch presentation (PDF), hoặc this review of Effective Java

21

Bạn có thể gói gọn các tham số liên quan bên trong một đối tượng không?

ví dụ, nếu các thông số giống như

 

MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) { 
    super(String house, String street, String town, String postcode, String country); 
    this.foo = foo; 
    this.bar = bar; 
 

sau đó bạn thay vì có thể có:

 

MyClass(Address homeAddress, int foo, double bar) { 
    super(homeAddress); 
    this.foo = foo; 
    this.bar = bar; 
} 
 
5

Vâng, bằng cách sử dụng mô hình xây dựng có thể là một giải pháp.

Nhưng một khi bạn đến 20-30 tham số, tôi đoán rằng có mối quan hệ cao giữa các tham số. Vì vậy, (như đề nghị) gói chúng vào các đối tượng dữ liệu hợp lý lành mạnh có thể làm cho ý nghĩa nhất. Bằng cách này, đối tượng dữ liệu có thể kiểm tra tính hợp lệ của các ràng buộc giữa các tham số.

Đối với tất cả các dự án của tôi trong quá khứ, một khi tôi đã đến mức có quá nhiều tham số (và đó là 8 không 28!) Tôi đã có thể khử trùng mã bằng cách tạo một mô hình dữ liệu tốt hơn.

2

Tôi thực sự có thể khuyên bạn sử dụng Immutables hoặc POJOBuilder khi sử dụng mẫu trình tạo.

Các vấn đề liên quan