2009-09-19 37 views
20

Hiện tại tôi đã rất quan tâm đến "mẫu thiết kế" này. Tôi không chắc chắn mặc dù nếu có những thiếu sót bằng cách sử dụng này thực hiện nghiêm ngặt nhà nước toàn cầu. Vì vậy, khi nào bạn nghĩ rằng không thực hành singleton trong một ứng dụng?Mẫu thiết kế Singleton: Cạm bẫy

+0

[Ở đây] (https://www.michaelsafyan.com/tech/design/patterns/singleton) là một bài đọc hay về singleton là một hình mẫu chống. – RBT

Trả lời

35

Singleton thường là một ý tưởng tồi nếu bạn đang làm thử nghiệm đơn vị, và nói chung một ý tưởng tồi là không làm thử nghiệm đơn vị (hoặc BDD hoặc kiểm tra chấp nhận).

Làm cho các đối tượng có trạng thái toàn cầu nghĩa là đơn vị kiểm tra bạn viết liên quan đến các đối tượng này sẽ bị cô lập và tách rời nhau. Thay vào đó, bạn sẽ phải lo lắng về việc đặt lại trạng thái cho mỗi bài kiểm tra và tin tôi ... điều đó không bao giờ được thực hiện 100% thời gian. Nếu bạn không thiết lập lại trạng thái toàn cầu thì bạn bắt đầu nhận được rất khó hiểu và khó sửa lỗi trong các bài kiểm tra của bạn mà lãng phí thời gian.

Trạng thái toàn cầu cũng làm tăng sự ghép nối trong mã của bạn và làm cho việc tái cấu trúc trở nên rất khó khăn.

Phương pháp lý tưởng là sử dụng hộp chứa IoC/DI (Spring, Guice, v.v.) để yêu cầu đối tượng. Các vùng chứa này thường có cách làm cho các đối tượng xuất hiện dưới dạng 'Singletons' nhưng chúng cũng có cách sửa đổi hành vi đó tùy thuộc vào tình huống (ví dụ: kiểm tra đơn vị so với mã miền của bạn).

Tất cả điều này phụ thuộc vào quy mô của vấn đề của bạn tất nhiên. Nếu bạn đang lắp ráp một giàn khoan thử nghiệm 4 cấp để thử một cái gì đó thì hãy tiếp tục và sử dụng Singleton. Tuy nhiên, ngay sau khi dự án đó tiếp tục phát triển và phát triển lớn hơn và phức tạp hơn thì hãy tái cấu trúc Singleton.

+0

Vì vậy, bạn có nghĩa là singletons là * không bao giờ * đủ điều kiện để sử dụng trong các dự án thực tế (và phát hiện một singleton trong một dự án thực sự tự động tương đương với mã code bất kể trường hợp sử dụng)? – Pacerier

+0

Tôi ngửi thấy một con troll ... –

+0

Đừng kiềm chế mùi sau đó. Câu trả lời của bạn cho thấy rằng singletons chỉ được sử dụng cho "giai đoạn ban đầu" mã và nên được factored trong tất cả các dự án trưởng thành phát triển lớn hơn. Vì vậy, bạn có nghĩa là người độc thân không bao giờ đủ điều kiện để sử dụng trong các dự án này, hoặc có trường hợp sử dụng hợp lệ? – Pacerier

3

Tôi sẽ sử dụng Singleton rất hiếm khi. Do tính chất của chúng (các đối tượng toàn cầu, tĩnh), chúng khó sử dụng trong đơn vị kiểm tra mã của bạn. Bạn cần phải thực hiện một số đồng bộ hóa hoặc xây dựng trong một số cơ chế khởi tạo lại để bạn có thể có phiên bản mới cho mỗi bài kiểm tra đơn vị. Có những trường hợp có ý nghĩa - ví dụ, một lớp cấu hình toàn cầu - nhưng chúng ít hơn nhiều so với những người mới đến singleton dường như tin. Tôi biết tôi đã trải qua một giai đoạn mà tôi thấy các ứng dụng của mẫu đơn ở khắp mọi nơi. Bây giờ tôi tránh nó bất cứ nơi nào tôi có thể và hoàn tác nó thông qua refactoring trong mã của tôi khi tôi đi qua một thực hiện không cần thiết.

7

Ngoài các vấn đề về thiết kế và kiểm tra được đề cập trong các bài đăng khác, có vấn đề với Singletons và trình nạp lớp. Singletons không thực sự là "đơn" cho mỗi JVM hoặc ứng dụng - chúng thực hiện điều này thông qua thuộc tính tĩnh, điều này thực sự có nghĩa là có một lớp cho mỗi lớp. Nếu có nhiều trình nạp lớp - như trong hầu hết các máy chủ ứng dụng - mỗi ứng dụng riêng biệt đều có trình nạp lớp mới, thậm chí nhiều cấp độ của trình nạp lớp được sử dụng trong EJB. Một cá thể đơn được nạp cho mỗi trình nạp lớp - tùy thuộc vào những gì bạn đang làm với singleton, có thể không tạo ra kết quả bạn mong đợi.

+1

@Nate, điều này nghe có vẻ thú vị, Bạn có thể cho tôi một ví dụ cụ thể không? – eric2323223

+0

Có nguồn có thẩm quyền nào cho yêu cầu của bạn không? Tại sao các trường hợp JRE không phân biệt các trường hợp riêng lẻ? – Pacerier

+0

@Pacerier http://www.oracle.com/technetwork/articles/java/singleton-1577166.html Các JRE riêng biệt sử dụng các cá thể đơn lẻ riêng biệt là trường hợp dự kiến ​​- vấn đề là một JRE đơn lẻ có thể có nhiều trình nạp lớp và do đó nhiều cá thể đơn lẻ . – Nate

18

Google Tech Talks đã có thời gian trước đây là bản trình bày hay về Global State and Singletons. Mẫu singleton tĩnh là điều ác, vì gây ra các tác dụng phụ không mong muốn và làm cho mã không thể thực hiện được. Singleton tĩnh là phiên bản OO của các biến toàn cầu.

Giải pháp là chỉ cần tạo một trường hợp đối tượng và chuyển cho người dùng thông qua việc tiêm phụ thuộc. Các khung công tác DI, chẳng hạn như Guice, giúp xác định loại đơn giản tốt (trong Guice chỉ chú thích một lớp với @Singleton). Có một cuộc thảo luận công nghệ tương tự được gọi là Don't Look For Things! đã thảo luận DI nhiều hơn.

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