Menu
CoddyTech

Mẫu Singleton

Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 54 trên 61.

Đôi khi, bạn cần có đúng một đối tượng trong toàn bộ chương trình, chẳng hạn như trình quản lý cấu hình, hệ thống ghi nhật ký hoặc kết nối cơ sở dữ liệu. Mẫu Singleton đảm bảo chỉ có một đối tượng tồn tại và cung cấp một điểm truy cập toàn cục đến đối tượng đó.

Trong C, ta triển khai cách này bằng một biến static bên trong tệp mã nguồn. Hãy nhớ rằng static ở phạm vi tệp có nghĩa là biến chỉ dùng riêng trong tệp đó và tồn tại suốt thời gian chạy của chương trình. Kết hợp với một hàm getter, cách này tạo nên Singleton của chúng ta:

// config.c
#include "config.h"
#include <stdlib.h>

struct Config {
    int max_connections;
    int timeout;
};

static Config* instance = NULL;

Config* get_config(void) {
    if (instance == NULL) {
        instance = malloc(sizeof(Config));
        instance->max_connections = 100;
        instance->timeout = 30;
    }
    return instance;
}

Điều kỳ diệu nằm ở get_config(). Lần gọi đầu tiên tạo và khởi tạo instance. Mỗi lần gọi tiếp theo đều trả về cùng một con trỏ.

Từ khóa static giúp instance giữ nguyên giá trị giữa các lần gọi hàm và ẩn với các tệp khác.

Thông qua phần đầu, người dùng chỉ thấy hàm getter. Họ không thể truy cập hoặc sửa đổi trực tiếp biến tĩnh. Dù bạn gọi get_config() bao nhiêu lần hoặc từ đâu, bạn luôn nhận được cùng một đối tượng.

challenge icon

Thử thách

Dễ

Hãy tạo một module Settings để quản lý cấu hình trên toàn ứng dụng bằng mẫu Singleton. Dù code của bạn yêu cầu cài đặt bao nhiêu lần, chương trình luôn trả về cùng một instance.

Bạn sẽ sắp xếp code trong ba tệp:

  • settings.h: Khai báo kiểu Settings không hiển thị cấu trúc bên trong bằng khai báo trước. Khai báo hàm get_settings trả về con trỏ đến instance Singleton, cùng các hàm getter và setter cho hai giá trị cấu hình: volume (số nguyên) và brightness (số nguyên). Các chỉ thị bảo vệ khi include rất cần thiết ở đây.
  • settings.c: Đây là nơi mọi thứ diễn ra. Định nghĩa struct Settings thực tế với các trường volume và brightness. Tạo một biến con trỏ static để giữ instance duy nhất (khởi tạo bằng NULL). Cài đặt get_settings sao cho lần gọi đầu tiên cấp phát và khởi tạo instance với các giá trị mặc định (volume: 50, brightness: 75), còn những lần gọi sau chỉ trả về instance hiện có. Cài đặt các hàm getter và setter để truy cập và thay đổi những trường ẩn.
  • main.c: Chứng minh Singleton hoạt động chính xác. Đọc hai số nguyên biểu thị giá trị volume và brightness mới. Gọi get_settings hai lần, lưu kết quả vào hai biến con trỏ khác nhau. Dùng con trỏ thứ nhất để cập nhật volume và brightness bằng các giá trị đầu vào. Sau đó, dùng con trỏ thứ hai để lấy và in ra cả hai giá trị. Nếu Singleton hoạt động, các thay đổi qua một con trỏ sẽ hiển thị qua con trỏ còn lại.

Chương trình nhận hai đầu vào:

  1. Giá trị volume mới
  2. Giá trị brightness mới

In volume và brightness trên các dòng riêng sau khi thay đổi chúng qua một con trỏ và đọc qua con trỏ khác.

Đầu ra mẫu khi đầu vào là 80 và 100:

80
100

Đầu ra mẫu khi đầu vào là 25 và 60:

25
60

Đầu ra mẫu khi đầu vào là 0 và 50:

0
50

Điểm mấu chốt là cả hai con trỏ đều trỏ đến cùng một đối tượng trong bộ nhớ: đó chính là bản chất của mẫu Singleton. Biến static trong tệp mã nguồn đảm bảo chỉ có một instance tồn tại và instance đó tồn tại suốt vòng đời của chương trình.

Tự làm thử

#include <stdio.h>
#include "settings.h"

int main() {
    int new_volume, new_brightness;
    scanf("%d", &new_volume);
    scanf("%d", &new_brightness);
    
    // TODO: Gọi get_settings hai lần và lưu kết quả vào hai biến con trỏ khác nhau
    
    
    // TODO: Dùng con trỏ thứ nhất để cập nhật âm lượng và độ sáng bằng các giá trị đầu vào
    
    
    // TODO: Dùng con trỏ thứ hai để lấy và in ra âm lượng cùng độ sáng
    // (Điều này cho thấy cả hai con trỏ đều trỏ đến cùng một instance singleton)
    
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C online