Câu trả lời dưới đây là sai, nhưng tôi sẽ giữ nó để người khác học hỏi từ nó (xem bên dưới)
Trong ExampleA, bạn có thể sử dụng cùng một Configthể hiện trên nhiều lớp. Tuy nhiên, nếu chỉ có một Configphiên bản trong toàn bộ ứng dụng, hãy xem xét áp dụng mẫu Singleton trên Configđể tránh có nhiều phiên bản Config. Và nếu Configlà Singleton, bạn có thể thực hiện các thao tác sau:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
Trong ExampleB, mặt khác, bạn sẽ luôn có được một trường hợp riêng biệt của Configtừng thể hiện của ExampleB.
Phiên bản nào bạn nên áp dụng thực sự phụ thuộc vào cách ứng dụng sẽ xử lý các trường hợp Config:
- nếu mỗi trường hợp
ExampleXnên có một thể hiện riêng biệt Config, hãy đi với ExampleB;
- nếu mỗi phiên bản
ExampleXsẽ chia sẻ một (và chỉ một) phiên bản của Config, sử dụng ExampleA with Config Singleton;
- nếu các trường hợp
ExampleXcó thể sử dụng các trường hợp khác nhau Config, hãy gắn bó với ExampleA.
Tại sao chuyển đổi Configthành Singleton là sai:
Tôi phải thừa nhận rằng tôi chỉ học về mẫu Singleton ngày hôm qua (đọc cuốn sách Head First về các mẫu thiết kế). Chắc chắn tôi đã đi và áp dụng nó cho ví dụ này, nhưng như nhiều người đã chỉ ra, một cách là một cách khác (một số đã khó hiểu hơn và chỉ nói "Bạn đang làm sai!"), Đây không phải là một ý tưởng tốt. Vì vậy, để ngăn người khác mắc lỗi tương tự mà tôi vừa mắc phải, dưới đây là tóm tắt lý do tại sao mẫu Singleton có thể gây hại (dựa trên các nhận xét và những gì tôi đã phát hiện ra)
Nếu ExampleAlấy tham chiếu riêng của nó đến Configthể hiện, các lớp sẽ được liên kết chặt chẽ. Sẽ không có cách nào để có một ExampleAphiên bản sử dụng một phiên bản khác của Config(giả sử một số lớp con). Điều này thật kinh khủng nếu bạn muốn kiểm tra ExampleAbằng cách sử dụng một ví dụ giả Configvì không có cách nào để cung cấp nó ExampleA.
Tiền đề của việc sẽ có một, và chỉ một, ví dụ Configcó thể nắm giữ ngay bây giờ , nhưng bạn không thể luôn chắc chắn rằng điều tương tự sẽ giữ trong tương lai . Nếu tại một thời điểm nào đó, nó chỉ ra rằng nhiều trường hợp Configsẽ được mong muốn, không có cách nào để đạt được điều này mà không cần viết lại mã.
Mặc dù trường hợp một và chỉ một Configcó thể đúng với mọi thời đại, nhưng có thể xảy ra rằng bạn muốn có thể sử dụng một số lớp con của Config(trong khi vẫn chỉ có một thể hiện). Nhưng, kể từ khi mã trực tiếp được thể hiện qua getInstance()các Config, mà là một staticphương pháp, không có cách nào để có được những lớp con. Một lần nữa, mã phải được viết lại.
Thực tế là việc ExampleAsử dụng Configsẽ bị ẩn, ít nhất là khi chỉ xem API của ExampleA. Điều này có thể hoặc không phải là một điều xấu, nhưng cá nhân tôi cảm thấy rằng điều này cảm thấy như một bất lợi; chẳng hạn, khi duy trì, không có cách đơn giản nào để tìm ra lớp nào sẽ bị ảnh hưởng bởi các thay đổi Configmà không xem xét việc thực hiện của mọi lớp khác.
Ngay cả khi việc ExampleAsử dụng Singleton Config không phải là vấn đề trong chính nó, nó vẫn có thể trở thành vấn đề từ quan điểm thử nghiệm. Các đối tượng Singleton sẽ mang trạng thái sẽ tồn tại cho đến khi chấm dứt ứng dụng. Đây có thể là một vấn đề khi chạy thử nghiệm đơn vị vì bạn muốn tách biệt một thử nghiệm với một thử nghiệm khác (nghĩa là đã thực hiện một thử nghiệm này sẽ không ảnh hưởng đến kết quả của thử nghiệm khác). Để khắc phục điều này, đối tượng Singleton phải bị hủy giữa mỗi lần chạy thử (có khả năng phải khởi động lại toàn bộ ứng dụng), điều này có thể tốn thời gian (không đề cập đến tẻ nhạt và gây phiền nhiễu).
Đã nói điều này, tôi rất vui vì tôi đã phạm sai lầm này ở đây và không phải trong việc thực hiện một ứng dụng thực sự. Trong thực tế, tôi đã thực sự xem xét việc viết lại mã mới nhất của mình để sử dụng mẫu Singleton cho một số lớp. Mặc dù tôi có thể dễ dàng hoàn nguyên các thay đổi (tất nhiên mọi thứ được lưu trữ trong SVN), tôi vẫn sẽ lãng phí thời gian để thực hiện.