GOF - Singleton

octofox·2021년 5월 28일
0

GOF - Gang Of Four

목록 보기
2/6

Singleton

어플리케이션 내부에 하나의 인스턴스만 존재하게 하도록 강제하는 패턴이다.
실제로 언제 사용할 수 있을까?
어플의 DB의 커넥션은 하나만 존재해도 된다.(하지만 웹과 같은 멀티 스레드 환경에서는 경합성 문제를 고려해보아야 한다.)
또… 어플리케이션의 테마도 페이지마다 다르지 않다면 하나의 설정이 모든 페이지에 영향을 미쳐야하니까 싱글톤을 사용할 수있을 것이다.

근데 class자체는 재사용성을 고려한 문법인데 그게 어떻게 가능한가?

class에는 크게 2곳의 메모리 공간이 존재한다.

한 곳은 class로 생성된 모든 instance가 참조할 수 있는 메모리 공간과 (static)
다른 한곳은 class로 만들어진 instance에 개별적으로 할당되는 메모리 공간이다.

여러개의 각각의 인스턴스도 공유가능한 공통 메모리 공간이 있다.
이곳을 정적인 공간 static 변수라고 부른다.

보통의 instance는 new 연산자를 만나 다른 변수에 할당되어 독립적인 메모리 공간을 가진다.

하지만 Singleton은 변태스럽게도 instance를 자기 class 안에 있는 정적 변수에 할당한다.

function이 재귀 호출이 가능하듯, class도 자신 안에서 자신의 instance 를 만들 수 있다.

내가 바보인건가 class 내부에 자신의 isntance를 둘 수 있는지 전혀 모르고 있었다.

그럼 class가 외부에서 new 연산자를 만나지 않고도 사용될 수 있더란 말이냐?
그렇다.

class의 static변수는 그 자체로 호출 가능하기 때문에 instance를 생성하지 않고도 static공간에 접근할 수 있다.

클래스이름::정적변수이름;
클래스이름::정적메소드();

하지만 사실 php와 같은 서버 사이드에서 singleton을 사용 할 수 있는 경우의 수는 많이 없다.

  1. 공유 자원 접근
  2. 복수의 시스템에서 하나의 자원에 접근할 때
  3. 유일한 객체가 필요할 때
  4. 값의 캐시가 필요할 때
class Config
{
    private static $Instance = NULL; // 참조체
    
    private function __construct()
    {
        // 생성자를 비어둔다. 객체 생성을 막는다.
    }
    
    private __clone()
    {
        // 복제 방지
    }
    
    public static function getInstance()
    {
        if(!isset(self::$Instance)){ // static 변수는 self로 접근한다.
            self::Instance = new self();
        }

        return self::Instance;
    }
}

$obj = Config::getInstance();
$obj = Config::getInstance();
$obj = Config::getInstance();

// 모든 $obj는 한 곳의 메모리 공간을 공유한다.
// 이미 생성되어진 instance를 반환받기 때문이다.

단점

PHP와 같은 멀티 쓰레드 환경에서는 단일 객체 생성을 보장 받지 못한다. 그래서 singleton객체 생성이 동시에 요청되는 경우에 경합성이 발생한다. 동일한 메모리에 동시에 접근하는 것을 말한다. 경합성 문제로 인해 2개의 객체가 만들어 질 수 도있다.
그렇게 오류를 초례한다.
PHP 개발 중에 PDO와 관련된 에러에 시달린 적이있다.
코드를 아무리 수정해보아도 같은 에러가 나왔다.
아파치를 재부팅해서 메모리를 해제해 보아야한다.
PDO에는 singleton을 사용하지 못하는 것인가?

singleton부분을 부팅시에 미리 처리하도록 만들라하는데 그건 나중에 모든 개발이 끝나고 최적화 과정해서 해야할 것 같다.

profile
개발자라고 우기는 노답 소년

0개의 댓글