싱글톤 패턴
Coddy C 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 54번째.
프로그램 전체에서 객체의 Singleton 패턴에 해당하는 instance가 정확히 하나만 필요한 경우가 있습니다. 구성 관리자, 로깅 시스템 또는 데이터베이스 연결이 그 예입니다. Singleton 패턴은 only 하나의 instance만 존재하도록 보장하고, 해당 instance에 대한 전역 액세스 지점을 제공합니다.
C에서는 소스 파일 내부의 static 변수를 사용하여 이를 구현합니다. 파일 범위에서 static은 변수가 해당 파일에서만 private하며 프로그램의 수명 동안 유지된다는 의미임을 기억하세요. getter function과 결합하면 Singleton이 생성됩니다.
// 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;
}마법은 get_config()에서 일어납니다. first call은 instance를 생성하고 초기화합니다. 이후의 모든 call은 same pointer를 반환합니다.
static 키워드는 instance가 function calls 사이에 값을 유지하고 다른 파일에서 계속 숨겨진 상태로 있도록 보장합니다.
헤더에서 사용자는 getter 함수만 볼 수 있습니다. 사용자는 static 변수에 직접 접근하거나 수정할 수 없습니다. get_config()를 몇 번 호출하든, 어디에서 get_config()를 call하든 항상 동일한 객체를 얻습니다.
챌린지
쉬움Singleton 패턴을 사용하여 애플리케이션 전반의 구성을 관리하는 Settings 모듈을 만들어 보겠습니다. 코드가 설정을 몇 번 요청하더라도 항상 정확히 동일한 인스턴스를 받게 됩니다.
코드를 세 개의 파일로 구성합니다:
settings.h: forward declaration을 사용하여 불투명한Settings타입을 Declare합니다(struct 본문은 숨겨진 상태로 유지됩니다). Singleton 인스턴스에 대한 포인터를 returns하는get_settingsfunction과 두 구성 값인volume(정수) 및brightness(정수)에 대한 getter와 setter functions를 Declare합니다. 여기서는 include guard가 필수입니다.settings.c: 실제 동작이 이루어지는 곳입니다.volume및brightnessfields를 포함하는 실제Settingsstruct를 Define합니다. 단일 인스턴스를 hold할staticpointer variable을 Create하고NULL로 초기화합니다. 첫 번째 Call에서 인스턴스를 할당하고 기본값(volume: 50, brightness: 75)으로 초기화하며, subsequent calls에서는 existing 인스턴스를 단순히 return하도록get_settingsfunction을 Implement합니다. 숨겨진 fields에 접근하고 수정하도록 getter와 setter functions를 Implement합니다.main.c: Singleton이 올바르게 작동하는지 보여 줍니다. 새로운 volume 및 brightness 값을 나타내는 두 정수를 읽습니다.get_settings를 두 번 Call하고 결과를 서로 different한 두 pointer variables에 저장합니다. First pointer를 사용하여 input 값으로 volume과 brightness를 업데이트합니다. 그런 다음 second pointer를 사용하여 두 값을 retrieve하고 print합니다. Singleton이 작동한다면, 한 pointer를 통해 변경한 내용이 다른 pointer를 통해서도 보입니다.
프로그램은 두 개의 입력을 받습니다:
- 새로운 volume 값
- 새로운 brightness 값
한 pointer를 통해 값을 수정한 후 다른 pointer를 통해 읽어서 volume과 brightness를 별도의 줄에 print합니다.
입력이 80 및 100일 때의 예시 출력:
80
100입력이 25 및 60일 때의 예시 출력:
25
60입력이 0 및 50일 때의 예시 출력:
0
50핵심은 both pointers가 메모리에서 동일한 객체를 가리킨다는 점입니다. 이것이 바로 Singleton 패턴의 본질입니다. source file 내부의 static variable은 only 하나의 인스턴스만 존재하도록 보장하며, 전체 프로그램 수명 동안 유지됩니다.
직접 해보기
#include <stdio.h>
#include "settings.h"
int main() {
int new_volume, new_brightness;
scanf("%d", &new_volume);
scanf("%d", &new_brightness);
// TODO: get_settings를 두 번 호출하고 두 개의 다른 포인터 변수에 저장하세요
// TODO: 첫 번째 포인터를 사용하여 입력 값으로 volume과 brightness를 업데이트하세요
// TODO: 두 번째 포인터를 사용하여 volume과 brightness를 가져와 출력하세요
// (이는 두 포인터가 동일한 싱글톤 인스턴스를 가리킨다는 것을 보여줍니다)
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C 컴파일러