Là một khởi tạo tĩnh lớn một mùi mã?


8

Tôi đang mở rộng SimpleExpandableListAdaptertrong Android. Tôi không nghĩ bộ điều hợp của Android được triển khai rất tốt, trong đó các nhà xây dựng của nó có một số lượng lớn các đối số khá phức tạp và nó không có setters hoặc trình xây dựng. Trong lớp của tôi, hầu hết các đối số đó không phụ thuộc vào lớp gọi nên tôi muốn xây dựng chúng trong nội bộ. Tuy nhiên, các đối số được lồng nhau Listvà các mảng của int và chuỗi cần được xây dựng theo chương trình.

Vì không có gì có thể được gọi trước hàm supertạo và các phương thức cá thể không thể được gọi trước khi supertrả về cuộc gọi, tôi hiện có một số phương thức tĩnh mà tôi gọi từ supercuộc gọi:

super(getContext(), initGroupData(), groupLayout, initGroupFrom(), initGroupTo(),
        initChildData(), childLayout, initChildFrom(), initChildTo());

Tôi thấy có ba cách xử lý việc này: gọi các phương thức tĩnh như tôi bây giờ, có một trình khởi tạo tĩnh lớn có thể gọi các phương thức tương tự này để khởi tạo các biến tĩnh được sử dụng trong supercuộc gọi hoặc đóng gói tất cả các phương thức này vào trình xây dựng.

Tôi nghĩ ngay bây giờ tôi đang nghiêng về người xây dựng, nhưng tôi tự hỏi liệu có cách nào tốt hơn để xử lý việc này không.


1
Điều gì về một phương pháp / chức năng nhà máy?
Paulo Ebermann

Câu trả lời:


9

Có các hàm trợ giúp tĩnh để tạo đối số hàm tạo là một giải pháp hoàn toàn lành mạnh, nhưng các hàm này bị giới hạn trong các hoạt động mà chúng có thể thực hiện do chúng phải tạo chính xác một đối số và không thể giao tiếp với nhau.

Trong trường hợp chung nhất mà bạn muốn điều chỉnh một giao diện Constructor(A, B, C)thành một giao diện có thể sử dụng nhiều hơn Constructor(X, Y), bạn có thể định nghĩa một hàm tạo của trình trợ giúp riêng có một riêng ArgumentObjectvà các chuỗi cho hàm tạo hiện có. Hàm xây dựng có thể sử dụng nhiều hơn sau đó xâu chuỗi với hàm tạo của trình trợ giúp thông qua hàm trợ giúp tĩnh để tạo đối tượng đối số:

class Constructor {
  // constructor you want to wrap
  public Constructor(A a, B b, C c) { ... }
  // better constructor you are defining
  public Constructor(X x, Y y) { this(createArgumentObject(x, y)); }
  // helper constructor using an ArgumentObject
  private Constructor(ArgumentObject ao) { this(ao.a, ao.b, ao.c); }
  // helper to create the argument object
  private static ArgumentObject createArgumentObject(X x, Y y) { ... }
  private static class ArgumentObject { ... }
}

Trong các ngôn ngữ không có chuỗi hàm tạo trong cùng một lớp (chẳng hạn như C ++ 03), bạn sẽ phải xác định một lớp con trung gian cho hàm tạo của trình trợ giúp.

Tuy nhiên, kỹ thuật này chỉ đơn thuần là sự khái quát hóa việc sử dụng các hàm tĩnh của bạn trong các đối số của hàm tạo. Các giải pháp khác mà bạn đã đề xuất có nhiều nhược điểm khác nhau, đó là lý do tại sao tôi sẽ tránh chúng trừ khi có một lý do rất chính đáng để thích chúng:

  • thực hiện các nhà xây dựng tốt cần rất nhiều nỗ lực cho rất ít giá trị. Nếu hàm tạo mới đủ đơn giản, bạn có thể làm mà không cần trình xây dựng. Giả sử lớp bạn đang gói thực hiện xác nhận hợp lệ, bạn có thể đặt đối tượng đối số ở chế độ công khai để các đối số có thể được truyền bằng cách sử dụng Constructor(new Constructor.Arguments {{ foo = 42; bar = baz; }})thành ngữ.

  • sử dụng các biến tĩnh được tính toán trong khối khởi tạo tĩnh có ý nghĩa đối với dữ liệu thực sự tĩnh, nhưng phải cẩn thận để tránh trạng thái toàn cầu. Trừ khi việc khởi tạo rất đơn giản, bạn nên sử dụng các hàm tĩnh để khởi tạo các biến này để việc khởi tạo có thể kiểm tra được. Bây giờ, lợi thế duy nhất so với trực tiếp sử dụng các phương thức tĩnh là các giá trị chỉ được tính một lần và được sử dụng lại cho tất cả các khởi tạo.

    Vì câu hỏi của bạn cho thấy các khởi tạo này có thể phức tạp hơn, nên việc sử dụng các khối khởi tạo tĩnh là một điều không nên nếu việc kiểm tra là quan trọng đối với bạn. (Nếu không, bạn có nhiều vấn đề khẩn cấp hơn.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.