Cách tạo một Singleton trong C++

Cach Tao Mot Singleton Trong C



Trong C++, singleton là một nguyên tắc thiết kế đảm bảo sự hiện diện của một phiên bản duy nhất của lớp trong suốt chương trình và cung cấp một điểm truy cập toàn cầu tới phiên bản cụ thể đó.

Mẫu singleton thường được sử dụng khi bạn cần có một tài nguyên chung, duy nhất có thể truy cập trên toàn cầu, chẳng hạn như kết nối cơ sở dữ liệu, trình ghi nhật ký hoặc trình quản lý cấu hình. Bằng cách thực thi một phiên bản duy nhất, nó cho phép nhiều phần của chương trình truy cập và sửa đổi cùng một đối tượng, thúc đẩy tính nhất quán của dữ liệu và giảm nhu cầu về các biến toàn cục. Singleton có thể được sử dụng làm bộ đệm đối tượng trong đó các đối tượng được sử dụng thường xuyên hoặc tốn kém để tạo được lưu trữ và tái sử dụng trong suốt ứng dụng. Cách tiếp cận này giúp cải thiện hiệu suất bằng cách tránh việc tạo và khởi tạo đối tượng dư thừa.

Trong bài viết này, chúng tôi sẽ giải thích việc tạo một singleton và trình bày một ví dụ về cách điệu hóa một singleton trong chương trình C++.







Ví dụ 1: Tạo một Singleton đơn giản với quá trình khởi tạo Eager

Một singleton đơn giản với khả năng khởi tạo sớm là một mẫu thiết kế đảm bảo rằng chỉ một phiên bản của một lớp được tạo và nó được tạo một cách háo hức trong quá trình khởi tạo tĩnh.



Chúng tôi sẽ trình diễn đoạn mã cơ bản để tạo một singleton đơn giản với khả năng khởi tạo háo hức. Hãy bắt đầu với chương trình:



#include

lớp học đơn {
riêng tư :
tĩnh Singleton * ví dụ ;
Singleton ( ) { }
công cộng :
tĩnh Singleton * lấy sơ thẩm ( ) {
trở lại ví dụ ;
}
} ;


Singleton * Singleton :: ví dụ = Singleton mới ( ) ;

int chủ yếu ( ) {

Singleton * singletonInstance1 = Singleton :: lấy sơ thẩm ( ) ;

Singleton * singletonInstance2 = Singleton :: lấy sơ thẩm ( ) ;

tiêu chuẩn :: cout << 'singletonletonInstance1: ' << singletonInstance1 << tiêu chuẩn :: kết thúc ;

tiêu chuẩn :: cout << 'singletonletonInstance2: ' << singletonInstance2 << tiêu chuẩn :: kết thúc ;

trở lại 0 ;

}

Mã bao gồm tiêu đề cung cấp chức năng hoạt động với các luồng đầu vào và đầu ra, chẳng hạn như “std::cout”.





Sau khi bao gồm tệp tiêu đề, chúng tôi xác định lớp “Singleton” đại diện cho việc triển khai mẫu singleton. Nó có một hàm tạo riêng và một biến thành viên tĩnh riêng có tên là “instance”.

Sau đó, hàm getInstance() được triển khai dưới dạng hàm thành viên tĩnh công khai của lớp “Singleton”. Nó trả về thể hiện của singleton được lưu trữ trong thể hiện biến thành viên tĩnh. Phiên bản biến thành viên tĩnh được xác định và khởi tạo bên ngoài lớp với “Singleton* Singleton::instance = new Singleton();”. Dòng này khởi tạo thể hiện của lớp “Singleton” một cách háo hức trong quá trình khởi tạo tĩnh.



Trong hàm main(), chúng ta khai báo hai con trỏ, “singletonInstance1” và “singletonInstance2”, đồng thời gán giá trị được trả về bằng cách gọi Singleton::getInstance(). Vì thể hiện được khởi tạo một cách háo hức nên cả hai con trỏ đều trỏ đến cùng một thể hiện. Câu lệnh “std::cout” in địa chỉ bộ nhớ của “singletonInstance1” và “singletonInstance2” vào bảng điều khiển bằng cách sử dụng toán tử “<<” và “std::endl”.

Mã kết thúc bằng “return 0” cho biết việc thực hiện chương trình thành công.

Khi bạn chạy mã này, kết quả đầu ra sẽ như thế này:

Đầu ra hiển thị địa chỉ bộ nhớ của “singletonInstance1” và “singletonInstance2”. Vì cả hai con trỏ đều được gán với cùng một thể hiện được lấy từ Singleton::getInstance() nên chúng có cùng một địa chỉ bộ nhớ. Điều này thể hiện cách mẫu singleton đảm bảo rằng chỉ có một phiên bản duy nhất của lớp và các lệnh gọi getInstance() trong tương lai luôn dẫn đến cùng một phiên bản.

Ví dụ 2: Triển khai mẫu đơn với khởi tạo lười biếng

Phần minh họa này giải thích cách triển khai mẫu đơn với khởi tạo lười biếng và hiển thị cách sử dụng nó trong hàm main(). Giải thích từng bước của đoạn mã được cung cấp sau chương trình này:

#include

lớp học đơn {

riêng tư :

tĩnh Singleton * ví dụ ;

Singleton ( ) {

tiêu chuẩn :: cout << 'Đã tạo phiên bản Singleton.' << tiêu chuẩn :: kết thúc ;

}

công cộng :

tĩnh Singleton * lấy sơ thẩm ( ) {

nếu như ( ví dụ == nullptr ) {

ví dụ = Singleton mới ( ) ;

}

trở lại ví dụ ;

}

trống rỗng tin chương trình ( ) {

tiêu chuẩn :: cout << 'Xin chào từ Singleton!' << tiêu chuẩn :: kết thúc ;

}

~Singleton ( ) {

tiêu chuẩn :: cout << 'Phiên bản Singleton bị phá hủy.' << tiêu chuẩn :: kết thúc ;

}

} ;

Singleton * Singleton :: ví dụ = nullptr ;

int chủ yếu ( ) {

Singleton * singletonInstance1 = Singleton :: lấy sơ thẩm ( ) ;

singletonInstance1 -> tin chương trình ( ) ;

Singleton * singletonInstance2 = Singleton :: lấy sơ thẩm ( ) ;

singletonInstance2 -> tin chương trình ( ) ;

trở lại 0 ;

}

Chương trình bắt đầu bằng cách thêm tệp tiêu đề để thực hiện các tác vụ đầu vào/đầu ra. Sau đó, chúng ta khai báo và định nghĩa một lớp “Singleton”. Phiên bản duy nhất của lớp được giữ trong biến thành viên tĩnh riêng có tên là instance instance.

Bất cứ khi nào hàm tạo của lớp “Singleton” được gọi, nó sẽ tạo ra một thể hiện của lớp “Singleton”. Nó xuất thông báo “Singleton instance made” ra console bằng cách sử dụng “std::cout << … << std::endl;”. Hàm tạo không có bất kỳ tham số nào vì nó là hàm tạo mặc định. Nó được định nghĩa là Singleton() mà không có bất kỳ đối số nào. Chúng tôi khai báo nó là riêng tư, có nghĩa là nó chỉ có thể được gọi từ bên trong lớp. Điều này ngăn chặn việc khởi tạo trực tiếp lớp “Singleton” và đảm bảo rằng cách duy nhất để có được một phiên bản là thông qua hàm getInstance().

Phương thức getInstance() của lớp “Singleton” được khai báo là hàm thành viên tĩnh công khai. Nó có vai trò thiết lập và cấp quyền truy cập cho phiên bản singleton. Bên trong getInstance(), nó kiểm tra xem phiên bản đó có phải là “nullptr” hay không. Nếu đúng như vậy, biểu thị rằng phiên bản này chưa có sẵn, nó sử dụng hàm tạo riêng để khởi tạo một đối tượng mới của lớp “Singleton”.

Hàm showMessage() là một hàm thành viên đơn giản hiển thị câu “Xin chào từ Singleton!” tin nhắn. Hàm hủy của singleton được xác định. Nó được gọi ngầm khi chương trình kết thúc và in ra “Phiên bản Singleton bị phá hủy”. thông báo cho biết phiên bản singleton đã bị hủy. Phiên bản biến thành viên tĩnh ban đầu được định nghĩa là “nullptr”.

int main() bắt đầu định nghĩa hàm main(). Sau đó, “Singleton* singletonInstance1 = Singleton::getInstance();” gọi hàm getInstance() của lớp “Singleton” để lấy một con trỏ tới cá thể singleton. Nó gán con trỏ này cho biến “singletonInstance1”.

Sau đó, “singletonInstance1->showMessage();” sử dụng toán tử mũi tên (->) để gọi hàm showMessage() trên con trỏ “singletonInstance1”. Hàm này hiển thị thông báo được chỉ định trong đó tới bàn điều khiển. Sau đó, “Singleton* singletonInstance2 = Singleton::getInstance();” gọi lại hàm getInstance(), lấy một con trỏ khác tới cá thể singleton. Lần này, nó gán con trỏ cho biến “singletonInstance2”. “singletonInstance2->showMessage();” gọi hàm showMessage() trên con trỏ “singletonInstance2”. Hàm này hiển thị “Xin chào từ Singleton!” nhắn tin lại cho bàn điều khiển.

Cuối cùng, “return 0;” biểu thị sự kết thúc của hàm main() và chương trình trả về giá trị 0 biểu thị việc thực hiện chương trình thành công.

Đây là đầu ra của đoạn mã được giải thích trước đó:

Kết quả này xác nhận rằng lớp “Singleton” đảm bảo chỉ tạo một phiên bản và các lệnh gọi tiếp theo đến hàm getInstance() sẽ mang lại phiên bản tương tự một cách đáng tin cậy.

Phần kết luận

Tạo một singleton trong C++ là một khái niệm rất hữu ích. Trong bài đăng này, ban đầu chúng tôi đề cập đến phần giới thiệu về singleton. Hơn nữa, hai ví dụ được tạo ra để triển khai singleton trong C++. Hình minh họa đầu tiên cho thấy việc triển khai khởi tạo đơn lẻ háo hức. Trong khi đó, việc triển khai khởi tạo lười biếng của mẫu đơn được cung cấp trong ví dụ thứ hai của bài viết này. Hơn nữa, ảnh chụp nhanh của đầu ra được tạo ra cũng được hiển thị cho các chương trình tương ứng.