Có bất kỳ lựa chọn thay thế khả thi nào cho Mô hình GOF Singleton không?


91

Hãy đối mặt với nó. Mô hình Singleton là chủ đề gây tranh cãi lớn với đám đông lập trình viên ở cả hai bên hàng rào. Có những người cảm thấy Singleton không hơn gì một biến toàn cầu được tôn vinh, và những người khác thì thề theo khuôn mẫu và sử dụng nó không ngừng. Tuy nhiên, tôi không muốn Cuộc tranh cãi Singleton nằm ở trọng tâm của câu hỏi của tôi. Mọi người đều có thể kéo co và chiến đấu và xem ai thắng cho tất cả những gì tôi quan tâm . Điều tôi muốn nói là, tôi không tin có một câu trả lời chính xác và tôi không cố ý thổi phồng những cuộc cãi vã của đảng phái. Tôi chỉ quan tâm đến các lựa chọn thay thế singleton khi tôi đặt câu hỏi:

Có bất kỳ lựa chọn thay thế cụ thể nào cho Mô hình GOF Singleton không?

Ví dụ, nhiều lần khi tôi đã sử dụng mô hình singleton trong quá khứ, tôi chỉ đơn giản quan tâm đến việc bảo toàn trạng thái / giá trị của một hoặc một số biến. Tuy nhiên, trạng thái / giá trị của các biến có thể được giữ nguyên giữa mỗi lần khởi tạo của lớp bằng cách sử dụng các biến tĩnh thay vì sử dụng mẫu singleton.

Bạn có ý tưởng nào khác?

CHỈNH SỬA: Tôi không thực sự muốn đây là một bài đăng khác về "cách sử dụng singleton một cách chính xác." Một lần nữa, tôi đang tìm cách để tránh nó. Để giải trí, ok? Tôi đoán tôi đang hỏi một câu hoàn toàn mang tính học thuật bằng giọng nói trong đoạn giới thiệu phim hay nhất của bạn, "Trong một vũ trụ song song không có singleton, chúng ta có thể làm gì?"


Gì? Nó không tốt cũng không xấu, nhưng làm thế nào tôi có thể thay thế nó? Đối với tất cả những người nói rằng nó tốt - đừng tham gia. Tất cả những gì bạn nói rằng nó tồi tệ, hãy chứng minh điều đó bằng cách cho tôi thấy tôi có thể sống như thế nào nếu không có nó. Nghe có vẻ tranh luận với tôi.
S.Lott

@CodingWithoutComents: đã đọc toàn bộ bài đăng. Đó là cách tôi có cảm giác "không trả lời nếu bạn cho rằng người Singleton vẫn ổn".
S.Lott

2
Vâng, nếu đó là cách nó xảy ra, tôi xin lỗi. Tôi nghĩ rằng tôi đã thực hiện các bước quan trọng để tránh phân cực. Tôi nghĩ tôi hỏi những câu hỏi trong một cách mà cả những người yêu thích và ghét Singletons cả hai có thể đi xa với điều đó như một lập trình viên chúng ta đều có sự lựa chọn - rằng họ không bao giờ chỉ có một đúng cách
CodingWithoutComments

Nếu tôi sử dụng Singletons, tôi không có khả năng đóng góp về cách làm việc xung quanh chúng. Nghe có vẻ phân cực với tôi.
S.Lott

9
Tôi sử dụng Singletons hàng ngày nhưng điều đó có ngăn tôi nghĩ rằng có thể có cách tốt hơn để làm mọi việc không? Mẫu thiết kế chỉ mới xuất hiện được 14 năm. Tôi có coi chúng là lẽ thật trong Kinh thánh không? Chúng ta có ngừng cố gắng suy nghĩ bên ngoài chiếc hộp không? Chúng ta không cố gắng đề cao kỷ luật của CS?
CodingWithoutComments

Câu trả lời:


76

Alex Miller trong " Những mẫu tôi ghét " đã trích dẫn những điều sau:

"Khi một singleton dường như là câu trả lời, tôi thấy nó thường khôn ngoan hơn nếu:

  1. Tạo giao diện và triển khai mặc định cho singleton của bạn
  2. Xây dựng một phiên bản triển khai mặc định của bạn ở “đầu” hệ thống của bạn. Điều này có thể nằm trong cấu hình Spring, hoặc trong mã, hoặc được định nghĩa theo nhiều cách khác nhau tùy thuộc vào hệ thống của bạn.
  3. Truyền cá thể đơn lẻ vào từng thành phần cần nó (chèn phụ thuộc)

2
Tôi biết đây là năm 5 tuổi, nhưng bạn có thể mở rộng về điều này? Tôi nghĩ rằng tôi đã được dạy rằng cách phù hợp để tạo một singleton là với một giao diện. Tôi muốn quan tâm nếu những gì tôi đang làm là 'OK', và không khủng khiếp như tôi đã được nói.
Pureferret

97

Để hiểu cách thích hợp để giải quyết các Singletons, bạn cần hiểu những gì sai với Singletons (và trạng thái toàn cầu nói chung):

Singleton ẩn các phụ thuộc.

Tại sao điều đó lại quan trọng?

Bởi vì Nếu bạn ẩn các phụ thuộc, bạn có xu hướng mất dấu số lượng khớp nối.

Bạn có thể tranh luận rằng

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

đơn giản hơn

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

nhưng ít nhất API thứ hai cũng làm cho nó rõ ràng chính xác những người cộng tác của phương pháp là gì.

Vì vậy, cách giải quyết các Singletons không phải là sử dụng các biến tĩnh hoặc bộ định vị dịch vụ, mà là thay đổi các lớp Singleton thành các thể hiện, được khởi tạo trong phạm vi mà chúng có ý nghĩa và được đưa vào các thành phần và phương thức cần chúng. Bạn có thể sử dụng IoC-framework để xử lý điều này hoặc bạn có thể làm điều đó theo cách thủ công, nhưng điều quan trọng là loại bỏ trạng thái toàn cục của bạn và làm cho các phụ thuộc và cộng tác rõ ràng.


+1 Để thảo luận về gốc rễ của vấn đề, không chỉ là cách giải quyết vấn đề.
Phil

9
Trong một ứng dụng nhiều tầng chính thức, phương pháp thứ hai thường tạo ra một lượng lớn mã không cần thiết. Bằng cách làm ô nhiễm mã của tầng giữa với logic để chuyển đến các tầng thấp hơn, các đối tượng không cần thiết ở cấp đó, không phải chúng ta đang tạo ra các phụ thuộc không cần thiết sao? Giả sử cấp 4 trong ngăn xếp điều hướng bắt đầu một hành động nền, chẳng hạn như tải lên tệp. Bây giờ, giả sử bạn muốn thông báo cho người dùng khi nó hoàn tất nhưng khi đó, người dùng có thể đang ở trong một phần hoàn toàn khác của ứng dụng, phần này chỉ có chung cấp 1 với chế độ xem khởi tạo. Tấn mã không cần thiết ...
Hari Singh Karam

1
@RasmusFaber Một mẫu Singleton không ẩn các phần phụ thuộc. Bạn phàn nàn về việc ẩn các phụ thuộc là một mối quan tâm riêng biệt so với mẫu. Đúng là mẫu dễ mắc lỗi này, nhưng rất có thể thực thi mẫu IoC và Singleton với nhau một cách hài hòa. Ví dụ: tôi có thể tạo lib của bên thứ 3 cần quản lý vòng đời đặc biệt đối với các bản sao của nó và bất kỳ ai sử dụng lib của tôi vẫn nên "chuyển" một bản sao của singleton của tôi vào các lớp của họ bằng cách sử dụng Dependency Injection cổ điển thay vì "sky hook" singleton của tôi từ mọi điểm.
Martin Bliss

@HariKaramSingh, bạn có thể sử dụng mẫu đăng ký / xuất bản hoặc xe buýt sự kiện trên toàn hệ thống (phải được chia sẻ cho tất cả các bên liên quan, không phải đơn lẻ) để giải quyết vấn đề này.
Victor Sorokin

4
Ngoài ra, các mẫu pub / sub hoặc Observer cũng có thể tệ như việc "mất dấu khớp nối" như bất kỳ ai phải gỡ lỗi từng bước thông qua một khuôn khổ dựa nhiều vào chúng sẽ chứng thực điều đó. Ít nhất là với singleton, tên phương thức được gọi ở cùng vị trí với mã gọi :) Cá nhân, tôi nghĩ rằng tất cả các chiến lược này đều có vị trí của chúng và không có chiến lược nào có thể được thực hiện một cách mù quáng. Những người viết mã cẩu thả sẽ làm cho mì Ý không theo bất kỳ khuôn mẫu nào và những người lập trình có trách nhiệm không cần phải gánh nặng quá mức với những giới hạn về tư tưởng để tạo ra những đoạn mã thanh lịch.
Hari Karam Singh

14

Giải pháp tốt nhất mà tôi đã thử là sử dụng factory pattern để xây dựng các thể hiện của các lớp của bạn. Sử dụng mô hình, bạn có thể đảm bảo rằng chỉ có một thể hiện của một lớp được chia sẻ giữa các đối tượng sử dụng nó.

Tôi mặc dù nó sẽ phức tạp để quản lý, nhưng sau khi đọc bài đăng trên blog này "Tất cả các Singletons đã đi đâu?", nó có vẻ rất tự nhiên. Và ngoài ra, nó giúp ích rất nhiều cho việc cô lập các bài kiểm tra đơn vị của bạn.

Tóm lại, bạn cần phải làm gì? Bất cứ khi nào một đối tượng phụ thuộc vào đối tượng khác, nó sẽ chỉ nhận một thể hiện của nó thông qua hàm tạo của nó (không có từ khóa mới trong lớp của bạn).

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

Và sau đó, nhà máy.

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

Vì bạn chỉ khởi tạo nhà máy của mình một lần, nên sẽ có một lần khởi tạo exSingleton. Mỗi khi bạn gọi buildNeedy, phiên bản mới của NeedyClass sẽ được đóng gói với exSingleton.

Tôi hi vọng cái này giúp được. Xin vui lòng chỉ ra bất kỳ sai lầm.


5
để đảm bảo Nhà máy của bạn chỉ được khởi tạo khi bạn cần một trình tạo riêng và xác định phương thức buildNeedy là một phương thức tĩnh.
Julien Grenier 23/10/08

16
Julien nói đúng, bản sửa lỗi này có một lỗ hổng cơ bản, đó là bạn đang ngầm nói rằng bạn chỉ có thể khởi tạo một nhà máy. Nếu bạn thực hiện các biện pháp phòng ngừa cần thiết để đảm bảo rằng chỉ có một nhà máy được khởi tạo (ala những gì Julien đã nói), bạn sẽ kết thúc với ... một singleton! Trong thực tế, cách tiếp cận này chỉ thêm một lớp trừu tượng không cần thiết lên trên singleton.
Bob Somers, 07/07/09

Có một cách khác để chỉ có một Phiên bản. Bạn có thể khởi tạo nhà máy của mình chỉ một lần. Không cần thực thi điều này bởi trình biên dịch. Điều này cũng hữu ích với các đơn vị mà bạn muốn một phiên bản khác.
frast

Đây là giải pháp tốt nhất mà tôi từng thấy cho vấn đề được giải quyết sai với các singleton - thêm các phụ thuộc mà không làm lộn xộn mọi lệnh gọi phương thức (và do đó thiết kế lại giao diện và cấu trúc lại các phụ thuộc của nó). Một sửa đổi nhỏ là hoàn hảo cho tình huống của tôi, nơi không quan trọng là chỉ có một phiên bản của "singleton", nhưng điều quan trọng là mọi người sẽ chia sẻ cùng một phiên bản theo mặc định (sửa đổi là: thay vì sử dụng nhà máy, hãy sử dụng tĩnh phương thức để thiết lập phiên bản chung bên ngoài và sử dụng phiên bản đó trong quá trình xây dựng).
meustrus

Vì vậy, về cơ bản lợi thế của cách tiếp cận này là bạn chỉ phải xáo trộn xung quanh một cá thể đối tượng (nhà máy) thay vì có khả năng là cả một loạt đối tượng (mà bạn đang chọn không sử dụng Singletons)?
Hari Karam Singh

9

Spring hoặc bất kỳ IoC-Container nào khác làm rất tốt việc đó. Vì các lớp được tạo và quản lý bên ngoài chính ứng dụng, nên vùng chứa có thể tạo các lớp đơn giản và chèn chúng khi cần thiết.


Có bất kỳ liên kết nào về các chủ đề nói trên không?
CodingWithoutComments 02/10/08

Các khuôn khổ này có vẻ cụ thể cho java - bất kỳ tùy chọn ngôn ngữ cụ thể nào khác không? Hay ngôn ngữ bất khả tri?
CodingWithoutComments

cho .NET: Castle Windsor Castleproject.org/container/index.html Microsoft Unity msdn.microsoft.com/en-us/library/cc468366.aspx Unity thực sự là một khuôn khổ chèn phụ thuộc, nhưng nó có thể sẽ hoạt động cho chủ đề này.
Erik van Brakel

1
tại sao không có quá nhiều phiếu bầu cho điều này? IOC là giải pháp hoàn hảo để tránh Singleton.
Sandeep Jindal

@CodingWithoutComments Tôi biết PHP có Vùng chứa dịch vụ Symfony. Mặc dù vậy, các công tử ruby ​​có những cách khác để tiêm các phụ thuộc. Bạn có một ngôn ngữ cụ thể mà bạn quan tâm không?
Bevelopper

9

Bạn không cần phải ra ngoài để tránh bất kỳ khuôn mẫu nào. Việc sử dụng một mẫu hoặc là một quyết định thiết kế hoặc một sự phù hợp tự nhiên (nó chỉ rơi vào đúng vị trí). Khi bạn thiết kế một hệ thống, bạn có thể lựa chọn sử dụng một mẫu hoặc không sử dụng mẫu. Tuy nhiên, bạn không nên tránh né bất cứ thứ gì mà cuối cùng vẫn là lựa chọn thiết kế.

Tôi không tránh Mô hình Singleton. Hoặc nó phù hợp và tôi sử dụng nó hoặc nó không phù hợp và tôi không sử dụng nó. Tôi tin rằng nó chỉ đơn giản như vậy.

Sự phù hợp (hoặc thiếu) của Singleton phụ thuộc vào tình huống. Đó là một quyết định thiết kế phải được thực hiện và hậu quả của quyết định đó phải được hiểu (và được lập thành văn bản).


Tôi sẽ nói điều tương tự, nhưng nó không hoàn toàn trả lời câu hỏi của anh :)
Swati

2
Vui lòng nói về câu trả lời của bạn khi nó phù hợp hoặc không phù hợp. Xin vui lòng.
CodingWithoutComments

Nó trả lời câu hỏi. Tôi không có kỹ thuật để tránh sử dụng Singleton Pattern bởi vì tôi không cố gắng tránh nó và tôi không nghĩ rằng bất kỳ nhà phát triển nào cũng nên làm.
Thomas Owens

Tôi không nghĩ rằng bạn có thể khái quát hóa khi nó phù hợp hoặc không phù hợp. Đó là tất cả các dự án cụ thể và phụ thuộc rất nhiều vào thiết kế của hệ thống được đề cập. Tôi không sử dụng "quy tắc ngón tay cái" cho những quyết định như thế này.
Thomas Owens

Hừ! Tôi không hiểu tại sao điều này lại bị bỏ phiếu. Tôi đã trả lời câu hỏi - Kỹ thuật của bạn để tránh sử dụng Mô hình Singleton là gì? - bằng cách nói rằng tôi không có kỹ thuật vì tôi không đi hết cách để tránh khuôn mẫu. Những người phản đối có thể giải thích thêm về lý do của họ không?
Thomas Owens

5

Monostate (được mô tả trong Phát triển phần mềm Agile của Robert C. Martin) là một giải pháp thay thế cho singleton. Trong mẫu này, dữ liệu của lớp đều là tĩnh nhưng getters / setters là không tĩnh.

Ví dụ:

public class MonoStateExample
{
    private static int x;

    public int getX()
    {
        return x;
    }

    public void setX(int xVal)
    {
        x = xVal;
    }
}

public class MonoDriver
{
    public static void main(String args[])
    {
        MonoStateExample m1 = new MonoStateExample();
        m1.setX(10);

        MonoStateExample m2 = new MonoStateExample();
        if(m1.getX() == m2.getX())
        {
            //singleton behavior
        }
    }
}

Monostate có hành vi tương tự như singleton nhưng làm như vậy theo cách mà lập trình viên không nhất thiết phải biết thực tế là một singleton đang được sử dụng.


Điều này xứng đáng được bình chọn nhiều hơn; Tôi đến đây từ Google để tìm kiếm bản cập nhật MonoState!
mahemoff

@Mark Đối với tôi, có vẻ như thiết kế này rất khó bị khóa về mặt an toàn của luồng. Tôi có tạo một khóa phiên bản cho mỗi biến tĩnh trong MonoStateExample hay tôi tạo một khóa mà tất cả các thuộc tính đều tận dụng? Cả hai đều có sự phân nhánh nghiêm trọng có thể dễ dàng giải quyết trong một mẫu Singleton.
Martin Bliss

Ví dụ này là một mẫu thay thế cho mẫu Singleton, nhưng không giải quyết các vấn đề của mẫu Singleton.
Sandeep Jindal

4

Các singleton pattern tồn tại vì có những tình huống khi một đối tượng duy nhất là cần thiết để cung cấp một tập hợp các dịch vụ .

Ngay cả khi trường hợp này xảy ra, tôi vẫn xem xét cách tiếp cận tạo các thẻ đơn bằng cách sử dụng trường / thuộc tính tĩnh toàn cục đại diện cho phiên bản, không phù hợp. Nó không phù hợp vì nó tạo ra sự phụ thuộc trong mã giữa trường tĩnh và đối tượng không phải là các dịch vụ mà đối tượng cung cấp.

Vì vậy, thay vì mẫu singleton cổ điển, tôi khuyên bạn nên sử dụng mẫu 'like' dịch vụ với các vùng chứa được phục vụ , trong đó thay vì sử dụng singleton của bạn thông qua trường tĩnh, bạn có được tham chiếu đến nó thông qua phương thức aa yêu cầu loại dịch vụ được yêu cầu.

*pseudocode* currentContainer.GetServiceByObjectType(singletonType)
//Under the covers the object might be a singleton, but this is hidden to the consumer.

thay vì toàn cầu duy nhất

*pseudocode* singletonType.Instance

Bằng cách này khi bạn muốn thay đổi kiểu của một đối tượng từ singleton sang một thứ khác, bạn sẽ có và dễ dàng thực hiện nó. Cũng như một lợi ích bổ sung, bạn không cần phải chuyển toàn bộ các phiên bản đối tượng cho mọi phương thức.

Ngoài ra, hãy xem Inversion of Control , ý tưởng là bằng cách hiển thị các đơn lẻ trực tiếp cho người tiêu dùng, bạn tạo ra sự phụ thuộc giữa người tiêu dùng và cá thể đối tượng, chứ không phải các dịch vụ đối tượng được cung cấp bởi đối tượng.

Ý kiến ​​của tôi là ẩn việc sử dụng mô hình singleton bất cứ khi nào có thể, bởi vì không phải lúc nào cũng có thể tránh được hoặc mong muốn.


Tôi không hoàn toàn theo dõi ví dụ của bạn về các thùng chứa được bảo dưỡng. Bạn có một tài nguyên trực tuyến mà bạn có thể liên kết đến không?
CodingWithoutComments

Hãy xem "Dự án Lâu đài - Thùng chứa Windsor" Castleproject.org/container/index.html . Thật không may là rất khó tìm thấy các ấn phẩm trừu tượng về chủ đề này.
Pop Catalin

2

Nếu bạn đang sử dụng Singleton để đại diện cho một đối tượng dữ liệu, bạn có thể chuyển một đối tượng dữ liệu xung quanh dưới dạng một tham số phương thức.

(mặc dù, tôi cho rằng đây là cách sử dụng Singleton sai lầm ngay từ đầu)


1

Nếu vấn đề của bạn là bạn muốn giữ trạng thái, bạn muốn có một lớp MumbleManager. Trước khi bạn bắt đầu làm việc với một hệ thống, khách hàng của bạn tạo một MumbleManager, trong đó Mumble là tên của hệ thống. Trạng thái được giữ lại thông qua đó. Rất có thể MumbleManager của bạn sẽ chứa một túi tài sản chứa trạng thái của bạn.

Kiểu này có cảm giác rất giống C và không giống đối tượng lắm - bạn sẽ thấy rằng các đối tượng xác định hệ thống của bạn đều sẽ có tham chiếu đến cùng một MumbleManager.


Không ủng hộ hay chống lại Singleton, tôi phải nói rằng giải pháp này là một mô hình chống lại. MumbleManager trở thành một "God class" chứa tất cả các loại kiến ​​thức khác nhau, vi phạm Trách nhiệm đơn lẻ. Nó cũng có thể là một Singleton cho tất cả các ứng dụng quan tâm.
Martin Bliss,

0

Sử dụng một đối tượng thuần túy và một đối tượng gốc. Nhà máy chịu trách nhiệm lập chính sách cho cá thể và chi tiết đối tượng thuần túy chỉ với thông tin cấu hình (ví dụ: nó chứa) và hành vi.


1
Không phải một Nhà máy thường là một đơn vị? Đó là cách tôi thường thấy các mẫu Factory được thực hiện.
Thomas Owens

0

Trên thực tế, nếu bạn thiết kế ngay từ đầu để tránh các Singeltons, bạn có thể không phải làm việc xung quanh việc không sử dụng Singletons bằng cách sử dụng các biến tĩnh. Khi sử dụng các biến tĩnh, ít nhiều bạn cũng đang tạo một Singleton, sự khác biệt duy nhất là bạn đang tạo các thể hiện đối tượng khác nhau, tuy nhiên bên trong chúng đều hoạt động như thể chúng đang sử dụng Singleton.

Bạn có thể đưa ra một ví dụ chi tiết về nơi bạn sử dụng Singleton hoặc nơi Singleton hiện đang được sử dụng và bạn đang cố gắng tránh sử dụng nó? Điều này có thể giúp mọi người tìm ra một giải pháp lạ mắt hơn để xử lý tình huống mà không có Singleton nào cả.

BTW, cá nhân tôi không có vấn đề gì với Singletons và tôi không thể hiểu những vấn đề mà người khác gặp phải về Singletons. Tôi thấy không có gì xấu về họ. Đó là, nếu bạn không lạm dụng chúng. Mọi kỹ thuật hữu ích đều có thể bị lạm dụng và nếu bị lạm dụng, nó sẽ dẫn đến kết quả tiêu cực. Một kỹ thuật khác thường được sử dụng sai là kế thừa. Vẫn không ai có thể nói thừa kế là điều gì đó xấu chỉ vì một số người lạm dụng nó một cách khủng khiếp.


0

Theo cá nhân tôi, cách hợp lý hơn nhiều để triển khai một thứ gì đó hoạt động như singleton là sử dụng lớp tĩnh hoàn toàn (thành viên tĩnh, phương thức tĩnh, thuộc tính tĩnh). Hầu hết thời gian tôi triển khai nó theo cách này (tôi không thể nghĩ ra bất kỳ sự khác biệt nào về hành vi theo quan điểm của người dùng)


0

Tôi nghĩ nơi tốt nhất để cảnh sát singleton là ở cấp độ thiết kế đẳng cấp. Ở giai đoạn này, bạn sẽ có thể vạch ra sự tương tác giữa các lớp và xem liệu có điều gì đó hoàn toàn, chắc chắn yêu cầu rằng chỉ có 1 thể hiện của lớp này tồn tại tại bất kỳ thời điểm nào của vòng đời ứng dụng hay không.

Nếu đúng như vậy, thì bạn có một singleton. Nếu bạn đang sử dụng các singleton như một sự tiện lợi trong quá trình viết mã thì bạn thực sự nên xem xét lại thiết kế của mình và cũng ngừng viết mã các singleton đã nói :)

Và vâng, 'cảnh sát' là từ tôi muốn nói ở đây hơn là 'tránh'. Singleton không phải là thứ nên tránh (giống như cách mà goto và các biến toàn cục không phải là thứ nên tránh). Thay vào đó, bạn nên giám sát việc sử dụng nó và đảm bảo rằng nó là phương pháp tốt nhất để hoàn thành những gì bạn muốn một cách hiệu quả.


1
Tôi hoàn toàn hiểu những gì bạn đang nói workmad. Và tôi hoàn toàn đồng ý. Tuy nhiên, câu trả lời của bạn vẫn không trả lời cụ thể câu hỏi của tôi. Tôi không muốn đây là một câu hỏi khác về "khi nào thì thích hợp để sử dụng singleton?" Tôi chỉ quan tâm đến các lựa chọn thay thế khả thi cho singleton.
CodingWithoutComments

0

Tôi sử dụng singleton chủ yếu là "vùng chứa phương thức", không có trạng thái nào cả. Nếu tôi cần chia sẻ các phương thức này với nhiều lớp và muốn tránh gánh nặng của việc khởi tạo và khởi tạo, tôi tạo một ngữ cảnh / phiên và khởi tạo tất cả các lớp ở đó; mọi thứ đề cập đến phiên cũng có quyền truy cập vào "singleton" do đó chứa.


0

Không được lập trình trong một môi trường hướng đối tượng mạnh mẽ (ví dụ như Java), tôi không hoàn toàn hiểu về sự phức tạp của cuộc thảo luận. Nhưng tôi đã triển khai một singleton trong PHP 4. Tôi đã làm điều đó như một cách để tạo một trình xử lý cơ sở dữ liệu 'hộp đen' tự động khởi tạo và không phải chuyển lên xuống các lệnh gọi hàm trong một khuôn khổ không hoàn chỉnh và có phần bị hỏng.

Sau khi đọc một số liên kết của các mẫu singleton, tôi không hoàn toàn chắc chắn rằng mình sẽ triển khai lại nó theo cách tương tự. Những gì thực sự cần thiết là nhiều đối tượng với bộ nhớ được chia sẻ (ví dụ: bộ xử lý cơ sở dữ liệu thực tế) và đây là những gì mà cuộc gọi của tôi đã biến thành.

Giống như hầu hết các mẫu và thuật toán, sử dụng một nút duy nhất 'chỉ vì nó thú vị' là Điều sai lầm cần làm. Tôi cần một lệnh gọi 'hộp đen' thực sự trông giống như một singleton. Và IMO đó là cách để giải quyết câu hỏi: nhận thức về mô hình, nhưng cũng xem xét phạm vi rộng hơn của nó và ở cấp độ nào thì thể hiện của nó cần phải là duy nhất.


-1

Ý bạn là gì, kỹ thuật của tôi để tránh nó là gì?

Để "tránh" nó, điều đó ngụ ý rằng có rất nhiều tình huống mà tôi gặp phải trong đó mô hình singleton phù hợp một cách tự nhiên, và do đó tôi phải thực hiện một số biện pháp để giải quyết những tình huống này.

Nhưng không có. Tôi không cần phải tránh mô hình singleton. Nó chỉ đơn giản là không phát sinh.

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.