Câu hỏi Khi nào sử dụng một Constructor và khi nào thì sử dụng phương thức getInstance () (các phương thức factory tĩnh)?


  1. Khi nào và làm thế nào chúng ta nên sử dụng một Constructor

    Foo bar = new Foo();
    
  2. Và khi nào và làm thế nào chúng ta nên sử dụng getInstance () (phương pháp nhà máy tĩnh)

    Foo bar = Foo.getInstance();
    

Sự khác biệt giữa hai điều này là gì, tôi luôn sử dụng cách thứ nhất nhưng khi nào thì sử dụng cách thứ 2?


76
2017-07-02 22:03


gốc


Bạn có tự viết cho mình không? Nếu không, bạn gọi cái gì để cung cấp nó? - Chris B.
vì vậy, việc thực hiện các lớp học chính nó có nghĩa là tôi đang thực hiện mô hình singleton, phải không? - zengr
Bạn có phải gọi điện thoại  getInstance(), hay là bạn viết một phương pháp gọi là getInstance()? - Chris B.
@chris Cả hai .... - zengr
Nếu câu hỏi là về constructor vs phương thức factory tĩnh, Tôi đề nghị làm rõ và thay đổi tiêu đề. - Pascal Thivent


Các câu trả lời:


Mọi người dường như tập trung vào những người độc thân trong khi tôi nghĩ rằng câu hỏi đó thực sự là về constructor vs phương thức factory tĩnh.

Đây thực sự là Mục 1: Xem xét các phương pháp nhà máy tĩnh thay vì các nhà thầu của Java hiệu quả bởi Joshua Bloch:

Mục 1: Xem xét các phương pháp nhà máy tĩnh thay vì các nhà thầu

Cách bình thường cho một lớp để cho phép   khách hàng để có được một thể hiện của chính nó   là cung cấp một nhà xây dựng công cộng.   Có một kỹ thuật khác nên   là một phần của mọi lập trình viên   bộ công cụ. Một lớp học có thể cung cấp cho công chúng    phương pháp nhà máy tĩnh, chỉ đơn giản là một phương thức tĩnh trả về một   ví dụ của lớp. Đây là một cách đơn giản   ví dụ từ Boolean (đóng hộp   lớp nguyên thủy cho kiểu nguyên thủy    boolean). Phương thức này dịch một   giá trị nguyên thủy boolean thành một    Boolean tham chiếu đối tượng:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Lưu ý rằng phương pháp nhà máy tĩnh là   không giống như Phương thức nhà máy   mô hình từ Mẫu thiết kế   [Gamma95, tr. 107]. Nhà máy tĩnh   phương pháp được mô tả trong mục này không có   tương đương trực tiếp trong Thiết kế   Mẫu.

Một lớp học có thể cung cấp cho khách hàng của mình   phương pháp nhà máy tĩnh thay vì, hoặc   ngoài ra, các nhà xây dựng.   Cung cấp phương thức nhà máy tĩnh   thay vì một nhà xây dựng công cộng đã   cả lợi thế và bất lợi.

Ưu điểm (trích dẫn sách):

  • Một lợi thế của phương pháp nhà máy tĩnh là, không giống như các nhà xây dựng, họ có tên.
  • Một lợi thế thứ hai của phương thức nhà máy tĩnh là, không giống như các nhà xây dựng, chúng không bắt buộc phải tạo một đối tượng mới mỗi khi chúng được gọi.
  • Một lợi thế thứ ba của phương thức nhà máy tĩnh là, không giống như các nhà xây dựng, chúng có thể trả về một đối tượng của bất kỳ kiểu con nào của kiểu trả về của chúng.
  • Ưu điểm thứ tư của phương pháp nhà máy tĩnh là chúng giảm độ dài của việc tạo ra các thể hiện kiểu tham số.

Nhược điểm (vẫn trích dẫn cuốn sách):

  • Nhược điểm chính của việc chỉ cung cấp các phương pháp nhà máy tĩnh là các lớp không có các hàm tạo công khai hoặc được bảo vệ không thể được phân lớp.
  • Một bất lợi thứ hai của phương pháp nhà máy tĩnh là họ không dễ phân biệt với các phương pháp tĩnh khác.

87
2017-07-02 23:16



1, đó là cách tôi cũng hiểu câu hỏi. - Dave O.
Người cuối cùng có thể được giảm thiểu phần nào. Tôi có xu hướng có một lớp bên trong tĩnh gọi là Nhà máy và các phương pháp newInstance khác nhau trong nó để làm cho nó rõ ràng hơn khi tôi tạo ra các phương pháp nhà máy. Nó đã giúp tôi tiết kiệm thời gian trong quá khứ. :) - Qberticus
@ Qberticus lớp bên trong dành riêng cho phương pháp nhà máy là một ý tưởng hay. Tôi sẽ thử nó, thx. - Dave O.
Chắc chắn các nhà xây dựng của các lớp phải ít nhất protected để cho phép subclassing, nhưng không mã khách hàng nhận được bất kỳ lợi thế thực sự từ việc tạo ra một đối tượng mới và gọi constructor của nó, so với gọi một phương pháp nhà máy tĩnh? Dường như với tôi rằng một lời gọi hàm dựng là ngữ nghĩa một phương thức thể hiện, trong khi trình tự "tạo đối tượng được đơn vị hóa và gọi hàm tạo của nó" là ngữ nghĩa tương đương với một lời gọi phương thức nhà máy tĩnh. - supercat


Bạn có hai câu hỏi: khi nào tôi nên gọi điện một getInstance() và khi nào tôi nên tạo nên một?

Nếu bạn quyết định có nên gọi một getInstance() phương pháp, thật dễ dàng. Bạn chỉ cần đọc tài liệu lớp học để tìm hiểu khi nào bạn nên gọi nó. Ví dụ, NumberFormat cung cấp một hàm tạo  một getInstance() phương pháp; các getInstance() phương pháp sẽ cung cấp cho bạn bản địa hóa NumberFormat. Dành cho Calendar, mặt khác, hàm tạo được bảo vệ. Bạn  để gọi getInstance() để có được một.

Nếu bạn quyết định có nên tạo một getInstance() phương pháp, bạn cần phải quyết định những gì bạn đang cố gắng để thực hiện. Hoặc là bạn không muốn mọi người gọi cho nhà xây dựng của bạn (bạn đang tạo singleton hoặc một nhà máy), hoặc bạn không nhớ (như trong NumberFormat ở trên, nơi họ đang khởi tạo một số đối tượng để thuận tiện cho người gọi).


Mẩu chuyện dài? Đừng lo lắng về việc tạo getInstance() các phương thức trong mã của riêng bạn. Nếu thời gian phát sinh khi chúng hữu ích, bạn sẽ biết. Và nói chung, nếu bạn có thể gọi hàm tạo của lớp, bạn có thể phải làm điều đó, ngay cả khi lớp đó cung cấp getInstance() phương pháp.


7
2017-07-02 22:08





Việc sử dụng các phương thức getInstance:

  • Nếu bạn muốn kiểm soát / hạn chế xây dựng, ví dụ: Singleton
  • triển khai mẫu Nhà máy, ví dụ: DriverManager.getConnection
  • Khi bạn muốn cung cấp tên tốt hơn về cách cá thể được xây dựng (các hàm tạo phải có cùng tên với tên lớp), hãy kiểm tra NumberFormat phương pháp nhà máy getCurrencyInstance, getIntegerInstance và những người khác làm ví dụ về điều này.

Nhưng hầu hết thời gian đối tượng của bạn sẽ đơn giản POJO và việc sử dụng các nhà thầu công cộng là giải pháp thực tế và rõ ràng nhất.

U1: getInstance từ lớp khác

Để trả về một thể hiện của một lớp khác:

public class FooFactory {
    public static Foo getInstance() {
        return new Foo();
    }
}

NumberFormat.getInstance các phương thức thực hiện điều này khi chúng thực sự trả về các thể hiện của DecimalFormat.

U2: Sự cố Singleton

Mẫu đơn lẻ hạn chế nhiều lợi ích của lập trình hướng đối tượng. Singletons thường có các nhà xây dựng tư nhân, do đó bạn không thể mở rộng chúng. Vì bạn sẽ truy cập nó thông qua phương thức getInstance của nó và không tham chiếu đến bất kỳ giao diện nào, bạn sẽ không thể trao đổi nó cho một triển khai khác.


7
2017-07-02 22:14



trong trường hợp của một mẫu nhà máy, một tên phương thức khác như 'createInstance' hoặc 'buildInstance' sẽ phù hợp hơn nhiều, nhưng vẫn có thể là điều mà người hỏi có thể muốn (âm thanh vẫn hơi mơ hồ và giống như một số bài tập về nhà với tôi) - jdehaan


Nếu bạn có thể sử dụng cả hai thì âm thanh đó giống như được triển khai kém mẫu đơn.

Sử dụng tùy chọn thứ hai nếu bạn dự định chỉ có một cá thể duy nhất của lớp trong hệ thống của bạn và làm cho hàm tạo riêng tư sau đó.

Sử dụng đầu tiên để cho phép xây dựng một số đối tượng của lớp.

NHƯNG không cho lớp của bạn cả hai khả năng.

Cẩn thận không sử dụng quá nhiều đơn, chỉ sử dụng chúng nếu thực sự chỉ có một cá thể tồn tại trong hệ thống nếu không bạn sẽ giới hạn khả năng sử dụng lại lớp của bạn trong các dự án khác. Nghe có vẻ thú vị khi có thể gọi getInstance từ mọi nơi trong dự án của bạn nhưng điều đó làm cho người không thực sự sở hữu ví dụ đó: không ai và / hoặc tất cả. Nếu bạn có rất nhiều đơn trong một dự án, bạn có thể đặt cược rằng hệ thống được thiết kế kém (thường). Singletons nên được sử dụng cẩn thận, cùng một lời khuyên hơn cho các biến toàn cục được áp dụng.


6
2017-07-02 22:04



Cập nhật câu hỏi, có một chút bối rối, xin lỗi - zengr
------> "Cẩn thận không sử dụng quá nhiều đơn" <------ - Bart van Heukelom


Một trường hợp mà tôi luôn thích một nhà máy tĩnh hơn một nhà xây dựng thường xuyên là khi tôi biết việc xây dựng đối tượng sẽ bị chậm lại. Tôi khởi tạo đơn giản trên constructor, nhưng nếu tôi cần tạo ra thứ gì đó nặng, tôi sẽ sử dụng một phương thức tĩnh và ghi lại hành vi.


1
2018-05-11 09:43





Singletons là ác. Các vấn đề tôi đã thấy xung quanh nó không phải là về tái sử dụng hoặc mở rộng của một hệ thống (mặc dù tôi có thể thấy như thế nào có thể xảy ra), nhiều hơn để tôi không thể đếm số lần tôi đã nhìn thấy lỗi mơ hồ trong một hệ thống phát sinh từ những người độc thân.

Nếu bạn cần sử dụng singleton, đảm bảo phạm vi của nó cực kỳ hẹp, tức là hạn chế một cách khôn ngoan số lượng đối tượng khác trong hệ thống của bạn biết về nó.


0
2017-07-02 22:20