PHP에서 데이터베이스에 액세스 할 수있는 싱글 톤의 사용 사례가 있습니까?


138

PDO를 통해 MySQL 데이터베이스에 액세스합니다. 데이터베이스에 대한 액세스를 설정하고 있으며 첫 번째 시도는 다음을 사용하는 것입니다.

내가 생각한 첫 번째 것은 global:

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');

function some_function() {
    global $db;
    $db->query('...');
}

이것은 나쁜 습관으로 간주됩니다. 약간의 검색 후, 나는 함께 결국 싱글 패턴 , 어떤

"클래스의 단일 인스턴스가 필요한 상황에 적용됩니다."

매뉴얼의 예에 따르면 다음과 같이해야합니다.

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }
}

function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');
}

some_function();

이것을 할 수 있는데 왜 비교적 큰 수업이 필요한가요?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }
}

function some_function() {
    Database::get()->query('...');
}

some_function();

이 마지막은 완벽하게 작동하며 $db더 이상 걱정할 필요가 없습니다.

더 작은 싱글 톤 클래스를 만들려면 어떻게해야합니까, 아니면 PHP에서 누락 된 싱글 톤에 대한 사용 사례가 있습니까?


이 관련 질문에 많은 자료와 토론이 있습니다 : '싱글 톤에 대해 무엇이 그렇게 나쁜가?'
FruitBreak

답변:


80

알았어, 내가 처음 커리어를 시작할 때 한동안 궁금했어. 다른 방법을 구현하고 정적 클래스를 사용하지 않기로 결정한 두 가지 이유가 있었지만 꽤 큰 클래스입니다.

하나는 당신이 당신이 절대로 하나 이상의 인스턴스를 가질 수 없다는 것을 절대적으로 확신하는 것을 발견 할 것이라는 것입니다. 두 번째 모니터, 두 번째 데이터베이스, 두 번째 서버 등으로 끝날 수 있습니다.

이런 일이 발생하면 정적 클래스를 사용한 경우 싱글 톤을 사용하는 것보다 훨씬 더 나쁜 리팩터링이 필요합니다. 싱글 톤 자체는 iffy 패턴이지만, 지능적인 팩토리 패턴으로 쉽게 변환 할 수 있습니다. 예를 들어, 싱글 톤이 getInstance ()를 통해 얻은 경우 getInstance (databaseName)로 쉽게 변경하고 다른 코드 변경없이 여러 데이터베이스를 허용 할 수 있습니다.

두 번째 문제는 테스트입니다 (솔직히 이것은 첫 번째 문제와 동일합니다). 때로는 데이터베이스를 모의 데이터베이스로 바꾸려고합니다. 실제로 이것은 데이터베이스 오브젝트의 두 번째 인스턴스입니다. 정적 클래스는 싱글 톤보다 정적 클래스로 처리하기가 훨씬 어렵습니다. 정적 클래스의 모든 단일 메소드가 아닌 getInstance () 메소드 만 조롱하면됩니다 (일부 언어에서는 매우 어려울 수 있음).

사람들은 "글로벌 (Globals)"이 나쁘다고 말할 때 그럴만한 이유가 있지만, 문제를 직접 해결할 때까지 항상 분명하지는 않습니다.

당신이 할 수있는 최선의 방법은 (당신이 한 것처럼) 물어보고 결정을 내리는 결과를 관찰하는 것입니다. 시간이 지남에 따라 코드의 진화를 해석 할 수있는 지식을 갖는 것이 처음부터 올바르게 수행하는 것보다 훨씬 중요합니다.


15
싱글 톤은 DI로 훌륭하게 저하되지만 getInstance(databaseName)코드 전체에서 인스턴스의 전역 저장소에 대한 참조를 산란하는 예는 아닙니까? 호출 getInstance할 코드에는 클라이언트 코드가 인스턴스를 삽입해야하므로 getInstance처음에는 호출 할 필요가 없습니다 .
Will Vousden

1
@ Will Vousden Correct, 그것은 일종의 스톱 갭입니다. 그것은 실제로 DI가 아니지만 꽤 가깝습니다. 예를 들어, getInstance (supportedDatabase)이고 리턴 된 인스턴스가 전달 된 데이터베이스를 기반으로 계산 된 경우 어떻게됩니까? 요점은 DI 프레임 워크를 가진 사람들이 준비가 될 때까지 겁 먹지 않도록하는 것입니다.
Bill K

320

싱글 톤은 PHP에서 거의 사용하지 않습니다.

객체가 공유 메모리에있는 언어에서는 싱글 톤을 사용하여 메모리 사용량을 낮출 수 있습니다. 두 개의 객체를 만드는 대신 전역 공유 응용 프로그램 메모리에서 기존 인스턴스를 참조합니다. PHP에는 그러한 응용 프로그램 메모리가 없습니다. 하나의 요청에서 생성 된 싱글 톤은 정확히 그 요청에 대해 유효합니다. 동시에 수행 된 다른 요청에서 생성 된 싱글 톤은 여전히 ​​완전히 다른 인스턴스입니다. 따라서 Singleton의 두 가지 주요 목적 중 하나는 여기에 적용되지 않습니다.

또한 개념적으로 응용 프로그램에 한 번만 존재할 수있는 많은 개체에는이를 적용하기 위해 언어 메커니즘이 필요하지 않습니다. 이 경우 필요 하나 개의 인스턴스를, 다음 또 다른 인스턴스를하지 않습니다 . 다른 인스턴스 가 없을 때만 ( 예 : 두 번째 인스턴스를 만들 때 새끼 고양이가 죽는 경우) 싱글턴에 대한 유스 케이스가있을 수 있습니다.

다른 목적은 동일한 요청 내의 인스턴스에 대한 글로벌 액세스 포인트를 갖는 것입니다. 이것이 바람직하게 들릴지 모르지만 전역 범위 (예 : 전역 및 정적)와의 결합을 생성하기 때문에 실제로는 그렇지 않습니다. 따라서 단위 테스트가 어려워지고 일반적으로 응용 프로그램의 유지 관리 부담이 줄어 듭니다. 이를 완화 할 수있는 방법이 있지만 일반적으로 많은 클래스에서 동일한 인스턴스가 필요한 경우 종속성 주입을 사용하십시오 .

PHP 에서 싱글 톤에 대한 내 슬라이드를 참조하십시오 -왜 나쁜지, 추가 정보 를 위해 응용 프로그램에서 제거하는 방법.

Singleton 패턴의 발명자 중 하나 인 Erich Gamma 조차도 오늘날이 패턴을 의심합니다.

"Singleton을 떨어 뜨리는 것을 선호합니다. 거의 항상 디자인 냄새입니다."

추가 자료

위의 후에도 여전히 결정에 도움이 필요한 경우 :

싱글 톤 결정 다이어그램


1
@ 고든 네. 그리고 요청간에 객체를 유지할 수 있었더라도 싱글 톤은 여전히 ​​몇 가지 SOLID 원칙을 위반하고 글로벌 상태를 도입합니다.
Gordon

4
흐름을 거스 르면 미안하지만 DI는 실제로 42 ctor 매개 변수 (또는 42 setFoo () 및 setBar () 호출이있는 클래스가있는 경우가 아니라면 Singleton이 사용하는 문제에 대한 해결책은 아닙니다. 작업). 그렇습니다. 불행히도 일부 앱은 이와 결합되어 있어야하며 많은 외부 요소에 의존해야합니다. PHP는 풀 언어이며 때로는 풀로 붙여야 할 것이 많습니다.
StasM

14
@ ctas 매개 변수가 42 개의 ctor 매개 변수를 가지고 있거나 많은 setter가 필요한 경우 잘못하고 있습니다. Clean Code Talks를 시청하십시오. 미안하지만, 이것에 대해 또 다른 설명을하지 않아도됩니다. 자세한 정보는 PHP 대화방에 문의하십시오.
Gordon

@Gordon PHP 대화방은 어디에 있습니까?
user658182

21

PHP에서 누가 싱글 톤을 필요로합니까?

싱글 톤에 대한 거의 모든 반대 의견은 기술적 인 관점에서 비롯된 것입니다. 그러나 그 범위도 매우 제한적입니다. 특히 PHP의 경우. 먼저 싱글 톤을 사용하는 몇 가지 이유를 나열한 다음 싱글 톤 사용에 대한 이의를 분석합니다. 먼저, 필요한 사람들 :

-많은 다른 환경에서 사용될 큰 프레임 워크 / 코드베이스를 코딩하는 사람들은 기존의 다른 프레임 워크 / 코드베이스와 함께 작업해야하며, 클라이언트 / 보스의 많은 변화, 심지어 기발한 요청을 구현해야합니다. / 관리 / 단위 지도자들이합니다.

싱글 톤 패턴은 자체 포함 적입니다. 완료되면 싱글 톤 클래스는 포함 된 모든 코드에서 엄격하며 메소드와 변수를 작성하는 방식과 동일하게 작동합니다. 그리고 주어진 요청에서 항상 같은 객체입니다. 두 개의 서로 다른 객체로 두 번 만들 수 없으므로 싱글 톤이 두 개, 세 개의 서로 다른 오래된 스파게티 코드베이스에 삽입 된 경우에도 코드에서 특정 지점에있는 단일 객체가 무엇인지 알 수 있습니다. 따라서 개발 목적으로 더 쉽게 만들 수 있습니다. 프로젝트에 많은 사람들이 있어도 주어진 코드베이스에서 단일 지점이 한 지점에서 초기화되는 것을 볼 때 그것이 무엇인지, 어떻게하는지, 어떻게하는지 알 수 있습니다. 기존 클래스 인 경우 해당 객체가 처음 작성된 위치를 추적해야합니다. 코드에서 특정 시점까지 호출 된 메소드 및 특정 상태 그러나 싱글 톤을 버리고 코딩하는 동안 적절한 디버깅 및 정보 메소드와 추적을 싱글 톤에 버렸다면 정확히 무엇인지 알 수 있습니다. 따라서 다른 철학으로 수행했거나 접촉하지 않은 사람들이 수행 한 코드를 통합해야 할 필요가 있으므로 다른 코드베이스로 작업해야하는 사람들이 더 쉬워집니다. (즉, 더 이상 존재하지 않는 공급 업체 프로젝트 회사)는 아무것도 지원하지 않습니다. 다른 철학으로 수행했거나 접촉하지 않은 사람들이 수행 한 코드를 통합해야 할 필요가 있으므로 다른 코드베이스로 작업해야하는 사람들이 더 쉬워집니다. (즉, 더 이상 존재하지 않는 공급 업체 프로젝트 회사)는 아무것도 지원하지 않습니다. 다른 철학으로 수행했거나 접촉하지 않은 사람들이 수행 한 코드를 통합해야 할 필요가 있으므로 다른 코드베이스로 작업해야하는 사람들이 더 쉬워집니다. (즉, 더 이상 존재하지 않는 공급 업체 프로젝트 회사)는 아무것도 지원하지 않습니다.

-타사 API , 서비스 및 웹 사이트를 다루어야 하는 사람들

자세히 살펴보면, 이전의 경우와 크게 다르지 않습니다. 타사 API, 서비스, 웹 사이트는 제어 할 수없는 외부의 격리 된 코드베이스와 같습니다. 무슨 일이든 일어날 수 있습니다. 따라서 싱글 톤 세션 / 사용자 클래스를 사용하면 OpenID , Facebook , Twitter 등과 같은 타사 제공 업체의 모든 종류의 세션 / 권한 구현을 관리 할 수 있으며 SAME 싱글 톤 객체에서 동시에 모든 작업을 수행 할 수 있습니다. -어떤 코드에 연결해도 특정 지점에서 알려진 상태로 쉽게 액세스 할 수 있습니다. 자신의 웹 사이트 / 애플리케이션에서 SAME 사용자를위한 여러 개의 다른 타사 API / 서비스에 대한 여러 세션을 생성하고 원하는 작업을 수행 할 수도 있습니다.

물론,이 모든 것들은 일반적인 클래스와 객체를 사용함으로써 전통적인 방법으로 어조가 될 수 있습니다. 여기서 중요한 것은 싱글 톤이 더 깔끔하고 깔끔하기 때문에 그러한 상황에서 전통적인 클래스 / 오브젝트 사용에 비해 관리 가능하고 테스트하기가 더 쉽기 때문입니다.

-빠른 개발이 필요한 사람들

싱글 톤의 전역 적 동작은 싱글 톤 클래스를 구성하는 프레임 워크를 사용하여 모든 종류의 코드를보다 쉽게 ​​빌드 할 수있게 해줍니다. 싱글 톤 클래스를 잘 구성하면 확립 된 성숙하고 설정된 메소드를 쉽게 사용할 수 있고 언제 어디서나 일관된 방식으로 사용할 수 있습니다. 수업을 완성하는 데 약간의 시간이 걸리지 만 그 후에는 견고하고 일관되며 유용합니다. 원하는 방식으로 단일 방법으로 많은 방법을 사용할 수 있으며, 이렇게하면 객체의 메모리 공간이 늘어날 수 있지만 빠른 개발에 필요한 시간이 훨씬 더 많이 절약됩니다. 응용 프로그램을 다른 통합 응용 프로그램에서 사용할 수 있으며 클라이언트 / 보스 / 프로젝트 관리자가 몇 가지 수정만으로 요청하는 새로운 기능을 사용할 수 있습니다.

당신은 아이디어를 얻습니다. 이제 싱글 톤에 대한 반대 의견과 유용한 것에 반대하는 부정한 성전으로 넘어가겠습니다 .

-가장 반대 의견은 테스트를 더 어렵게한다는 것입니다.

그리고 실제로 싱글 톤을 디버깅 할 것이라는 사실을 알고 적절한 예방 조치를 취하고 디버깅 루틴을 싱글 톤으로 코딩하여 쉽게 완화 할 수 있더라도 어느 정도까지는 가능합니다. 그러나 이것은 다른 코딩 철학 / 방법 / 패턴과 너무 다르지 않습니다. 단지, 싱글 톤은 비교적 새롭고 널리 보급되어 있지 않으므로 현재 테스트 방법은 비교할 수 없습니다. 그러나 이것은 프로그래밍 언어의 측면에서 다르지 않습니다. 스타일마다 스타일이 다릅니다.

이러한 반대 의견은 응용 프로그램이 개발 된 이유가 '테스트'가 아니며 테스트가 응용 프로그램 개발에 들어가는 유일한 단계 / 프로세스가 아니라는 사실을 무시한다는 점에서 동일합니다. 응용 프로그램은 프로덕션 용도로 개발되었습니다. '싱글 톤이 필요한 사람'섹션에서 설명했듯이 싱글 톤은 코드를 작동시키고 다른 많은 코드베이스 / 응용 프로그램 / 타사 서비스 내부에서 코드를 작성해야하는 복잡성에서 큰 거래를 줄일 수 있습니다. 테스트에서 손실 될 수있는 시간은 개발 및 배포에서 얻는 시간입니다. 이는 특히 타사 인증 / 응용 프로그램 / 통합 시대 (Facebook, Twitter, OpenID 등)에 더 유용하며 다음에 무엇이 있는지 잘 아는 사람에게 유용합니다.

이해할 만하지 만 프로그래머는 경력에 따라 매우 다른 상황에서 일합니다. 그리고 정의 된 부서가 다른 방식으로 정의 된 소프트웨어 / 애플리케이션을 편안한 방식으로, 예산 삭감 / 해고가 임박하지 않고 상대적으로 큰 회사에서 일하는 사람들을 위해 싸고 / 빠르고 / 신뢰할 수있는 방식의 싱글 톤은 그렇게 필요하지 않을 수도 있습니다. 그리고 그들은 이미 가지고있는 것에 방해가 될 수도 있습니다.

그러나 고객 / 관리자 / 프로젝트로부터 많은 다른 요청 (때로는 불합리한)을 구현해야하는 '민첩한'개발의 불참 한 트렌치에서 일해야하는 사람들을 위해 싱글 톤은 앞에서 설명한 이유 때문에 절약의 은혜입니다.

-또 다른 반대는 메모리 풋 프린트가 더 높다는 것입니다

각 클라이언트의 각 요청에 대해 새로운 싱글 톤이 존재하기 때문에 이는 PHP에 대한 이의 제기 일 수 있습니다. 잘못 구성되고 사용 된 싱글 톤을 사용하면 특정 시점에서 많은 사용자가 응용 프로그램에서 서비스를 제공하는 경우 응용 프로그램의 메모리 사용량이 높아질 수 있습니다.

그러나 이것은 코딩하는 동안 취할 수있는 모든 종류의 접근 방식에 유효합니다. 질문해야 할 질문은 이러한 싱글 톤에 의해 유지되고 처리되는 방법, 데이터입니까? 예를 들어, 많은 요청 응용 프로그램에서 필요로하는 경우 싱글 톤을 사용하지 않더라도 해당 메소드와 데이터는 코드를 통해 응용 프로그램에 어떤 형태로나 다른 형태로 나타납니다. 따라서 전통적인 클래스 객체를 코드 처리로 1/3로 초기화하고 3/4로 파괴하면 메모리가 얼마나 절약 될지 문제가됩니다.

이 방법을 사용하면 단일 톤의 사용 여부에 관계없이 질문이 무의미합니다. 불필요한 메소드가 없어야합니다. 따라서 싱글 톤에 대한 이의 제기는 실제로 사용하는 클래스에서 생성 된 객체의 불필요한 메소드, 데이터가 있다고 가정한다는 점에서 유쾌합니다.

- '여러 데이터베이스 연결을 유지 / 불가능하게 만드는 것'과 같은 일부 이의 제기

모든 사람들이 다중 데이터베이스 연결, 다중 데이터베이스 선택, 다중 데이터베이스 쿼리, 주어진 단일 톤의 다중 결과 세트를 단일 톤의 변수 / 배열에 유지하는 한 유지해야 할 때이 반대 의견을 이해할 수조차 없습니다. 그들은 필요하다. 배열에 유지하는 것만 큼 간단 할 수 있지만,이를 적용하기 위해 사용하려는 모든 방법을 발명 할 수 있습니다. 그러나 주어진 싱글 톤에서 변수와 배열을 사용하는 가장 간단한 경우를 살펴 보자.

아래가 주어진 데이터베이스 싱글 톤 안에 있다고 상상해보십시오.

$ this- > connections = 배열 (); (잘못된 구문, 방금 그림과 같이 입력했습니다. 변수의 올바른 선언은 public $ connections = array (); 사용법은 $ this-> connections [ 'connectionkey'] 자연 스럽습니다)

이 방식으로 특정 시간에 여러 연결을 배열로 설정하고 유지할 수 있습니다. 쿼리, 결과 집합 등도 마찬가지입니다.

$ this-> query (QUERYSTRING, 'queryname', $ this-> connections [ 'particulrconnection']) ;;

선택한 연결로 선택한 데이터베이스에 쿼리를 수행하고

$ this- > 결과

'queryname'키가있는 배열. 물론,이를 위해 쿼리 메소드를 코딩해야합니다.

이를 통해 필요한만큼 다른 데이터베이스 연결 및 결과 집합을 거의 무한대로 (자원 제한이 허용하는 한) 유지할 수 있습니다. 또한이 싱글 톤 클래스가 인스턴스화 된 특정 코드베이스의 특정 지점에서 모든 코드 조각에 사용할 수 있습니다.

코스 중, 결과 세트와 필요하지 않은 연결을 자연스럽게 해제해야하지만 말할 필요도 없으며 싱글 톤이나 다른 코딩 방법 / 스타일 / 개념에만 국한되지 않습니다.

이 시점에서 타사 응용 프로그램이나 서비스에 대한 여러 개의 연결 / 상태를 동일한 싱글 톤으로 유지 관리하는 방법을 확인할 수 있습니다. 그렇게 다르지 않습니다.

간단히 말해서, 싱글 톤 패턴은 프로그래밍하는 또 다른 방법 / 스타일 / 철학이며, 올바른 장소에서 올바른 방식으로 사용될 때 다른 방법만큼 유용합니다. 어느 것과도 다르지 않습니다.

싱글 톤을 버리는 대부분의 기사에서 '글로벌'에 대한 언급이 '악'임을 알 수 있습니다.

제대로 사용하지 않고 남용하거나 잘못 사용하는 것은 악한 일입니다. 그것은 어떤 언어, 어떤 코딩 개념, 방법으로 제한되지 않습니다. 'X is evil'와 같은 담요 진술을하는 누군가를 볼 때마다 그 기사에서 도망 치십시오. 특정 관점에서 수년간의 경험을 쌓은 결과 일지라도 제한된 관점의 산물 일 가능성은 매우 높습니다. 일반적으로 주어진 스타일 / 방법에서 너무 많은 일을 한 결과-전형적인 지적 보수 론입니다.

'글로벌은 악하다'에서 'iframe은 악하다'에 이르기까지 끝없는 예를들 수 있습니다. 약 10 년 전, 주어진 응용 프로그램에서 iframe 사용을 제안하는 것조차도 이단이었습니다. 그런 다음 Facebook, 모든 곳에서 iframe이 나오고 무슨 일이 있었는지 살펴보십시오. iframe은 더 이상 나쁘지 않습니다.

여전히 '악'이라고 주장하는 사람들이 있습니다. 때로는 좋은 이유가 있습니다. 보시다시피, 필요하고 잘 작동하는 iframe이 필요하기 때문에 전 세계가 계속 움직입니다.

프로그래머 / 코더 / 소프트웨어 엔지니어의 가장 중요한 자산은 자유롭고 개방적이며 유연한 마음입니다.


2
-1. 개방적이고 융통성있는 마음을 갖는 것이 개발자에게는 필수 자산이라는 데 동의하지만 Singleton을 반 패턴으로 사용하지는 않습니다. 위의 답변에는 Singleton의 본질과 효과에 대한 부정확 한 진술과 잘못된 결론이 포함되어 있지만 필자가 그것을 공표 할 수는 없습니다.
Gordon

-1. 나는 많은 싱글 톤이있는 프레임 워크를 경험해야했으며 자동 테스트는 불가능합니다. 브라우저에서 시행 착오를 통해 모든 것을 수동으로 테스트해야합니다. 코드 검토 (맞춤법, 구문 오류)로 일부 오류를 방지 할 수 있지만 기능 오류는 종종 숨겨져 있습니다. 이 테스트에는 단위 테스트보다 더 많은 시간이 필요합니다. 단위 테스트를 통해 다음과 같이 말할 수 있습니다.이 클래스는 독립적으로 작동하므로 오류가 다른 곳에 있어야합니다. 디버깅이 없으면 지루합니다.
Jim Martens 11

프레임 워크에는 로깅 및 오류 추적 기능이 내장되어 있어야합니다. 또한 격리 된 상태에서 제대로 작동하는 클래스는 더 넓은 응용 프로그램에 넣을 때 단일 형식으로도 제대로 작동합니다. 즉,이 경우 깨지는 것은 해당 싱글 톤과 상호 작용하는 다른 클래스 또는 함수 일 것입니다. 이것은 큰 응용 프로그램 내에서 일반적인 버그 추적과 다르지 않습니다. 응용 프로그램에 적절한 로깅이 없으면 매우 어렵습니다.
unity100

정확하지 않습니다. Testing-HELL을 생성하기 때문에 톤 톤은 확실히 사악합니다. :-) 그러나 앱당 하나의 단일 톤이 좋을 수 있습니다. 예를 들어, 통합 로깅 기능으로-모든 레거시 (일부 레거시 코드 앱 포함)에서 구현합니다.
Filip OvertoneSinger Rydlo

"테스트에서 잃어 버릴 수있는 시간 ..."이것은 정말 나쁜 습관과 사고 방식입니다. 이를 염두에두고 개발 된 모든 레거시 앱은 다시 작성해야하므로 유지 관리가 불가능 해졌습니다. 테스트가 없으면 새로운 기능이 개발되어 시스템의 다른 부분에서 문제가 발생하면 시간이 손실됩니다. 디버깅시 손실 된 시간, 해당 기능을 올바르게 사용할 수있는 사용자가 손실 한 시간, 앱 손실에 대한 확신 등
bogdancep

15

싱글 톤은 많은 사람들에 의해 반 패턴 으로 간주됩니다. 왜냐하면 그것들은 정말로 영광스러운 전역 변수이기 때문입니다. 실제로 클래스가 하나의 인스턴스 만 필요한 시나리오는 상대적으로 적습니다 . 일반적으로 하나의 인스턴스로 충분하기 때문에 단일 인스턴스로 구현하는 것이 완전히 필요하지 않습니다.

이 질문에 대답하기 위해 싱글 톤이 여기에서 과도하게 사용되는 것이 옳습니다. 간단한 변수 나 함수가 할 것입니다. 그러나 더 나은 (보다 강력한) 접근 방법은 종속성 주입 을 사용 하여 전역 변수의 필요성을 완전히 제거하는 것입니다.


그러나 싱글 톤은 DI로 매끄럽게 저하 될 수 있고 정적 클래스는 불가능합니다. 이는 정적 클래스의 실제 문제입니다.
Bill K

@Bill : 매우 사실이지만, 이것이 느슨한 함수 나 정적 방법보다는 DI 접근 방식을 옹호하는 이유입니다. :)
Will Vousden

Java와 같은 일부 언어에서는 정적 클래스 (또는 정적 클래스의 메서드)를 확장 할 수 없습니다. 따라서 미래 개발자에게 잠재적 인 문제 (또는 더 많은 작업)를 만들 수 있습니다. 따라서 정적 메소드는 특별한 필요가없는 한 일반적으로 피해야한다고 제안합니다.
Marvo

8

귀하의 예에서 겉보기에는 변하지 않는 단일 정보를 다루고 있습니다. 이 예제에서는 싱글 톤이 과도하게 사용되며 클래스에서 정적 함수를 사용하면 정상적으로 작동합니다.

더 많은 생각 : 당신은 패턴을 위해 패턴을 구현 한 경우를 경험할 수 있으며, 직감은 당신이 언급 한 이유로 "필요하지 않다"고 말합니다.

그러나 우리는 프로젝트의 규모와 범위를 모릅니다. 이것이 단순한 코드라면, 아마도 버릴 것입니다. 변경하지 않아도 될 것입니다. 그래도 정적 멤버를 사용하십시오. 그러나 유지 관리 코딩을 위해 프로젝트를 확장하거나 준비해야 할 필요가 있다고 생각되면 싱글 톤 패턴을 사용하는 것이 좋습니다.


1
와, 그냥 틀렸어 차이점의 핵심은 (질문에 대한 답변) 나중에 코드를 수정하여 두 번째 인스턴스를 추가하는 것이 얼마나 더 어렵다는 것입니다. 정적 메소드를 사용하는 경우이를 수행하기가 훨씬 어렵습니다. 이것은 Globals의 모든 문제가 조건이 바뀔 때 "제한된 조건 하에서 글로벌은 괜찮습니다"라고 말하는 것과 같습니다.
Bill K

@ 빌 K : 나는 당신에게 동의하고 복잡성이 전혀 없다면 싱글 톤을 사용할 것입니다. 그러나 나는 OP의 관점에서 질문에 대답하려고 노력했습니다. 그래서, 매우 제한된 경우에 과잉이라고 생각합니다. 물론 건축 또는 확장 성 문제와 수많은 고려 사항을 무시하고있었습니다. 왜 누군가가 왜 항상 싱글 톤을 사용해야하는지에 대한 설명과 함께 내 대답에주의를 기울여야 했습니까?
Paul Sasik

5

먼저, 나는 Singleton 패턴에 많은 용도를 찾지 못한다고 말하고 싶습니다. 왜 하나의 객체를 전체 응용 프로그램에서 철저하게 유지하고 싶습니까? 특히 데이터베이스의 경우 다른 데이터베이스 서버에 연결하려면 어떻게해야합니까? 매번 연결을 끊었다가 다시 연결해야합니까 ...? 어쨌든...

응용 프로그램에서 전역을 사용하는 데는 몇 가지 단점이 있습니다 (전통적인 Singleton 패턴 사용 방식).

  • 단위 테스트가 어려움
  • 의존성 주입 문제
  • 잠금 문제를 만들 수 있음 (멀티 스레드 응용 프로그램)

싱글 톤 인스턴스 대신 정적 클래스를 사용하면 싱글 톤의 가장 큰 문제는 정적 getInstance메소드 이므로 동일한 단점도 제공합니다 .

전통적인 getInstance방법 을 사용하지 않고 클래스가 가질 수있는 인스턴스 수를 제한 할 수 있습니다 .

class Single {

    static private $_instance = false;

    public function __construct() {
        if (self::$_instance)
           throw new RuntimeException('An instance of '.__CLASS__.' already exists');

        self::$_instance = true;
    }

    private function __clone() {
        throw new RuntimeException('Cannot clone a singleton class');
    }

    public function __destruct() {
        self::$_instance = false;
    }

}

$a = new Single;
$b = new Single; // error
$b = clone($a); // error
unset($a);
$b = new Single; // works

이것은 위에서 언급 한 첫 번째 사항에 도움이 될 것입니다 : 단위 테스팅 및 의존성 주입; 여전히 클래스의 단일 인스턴스가 응용 프로그램에 존재하는지 확인하십시오. 예를 들어 결과 객체를 모델 (MVC 패턴)에 전달하여 사용할 수 있습니다.


5

솔루션이 PHP 문서에 제시된 솔루션과 어떻게 다른지 고려하십시오. 실제로, "작은"차이점은 하나뿐입니다. 솔루션은 getter의 호출자에게 PDO인스턴스를 제공하는 반면, 문서의 호출자 Database::singletonDatabase인스턴스에 호출자를 제공 합니다 (그런 다음 getter를 사용하여 PDO인스턴스 를 얻음 ).

그래서 우리는 어떤 결론에 도달합니까?

  • 설명서 코드에서 호출자는 Database인스턴스를 얻습니다 . Database클래스는 (사실,이 노출 될 수 있습니다 해야 당신 '이 모든 문제에가는 다시 경우 노출)가보다 풍부한 또는 더 높은 수준의 인터페이스 PDO가 래핑 개체를.
  • 보다 다른 (더 풍부한) 유형을 반환하도록 구현을 변경 PDO하면 두 구현이 동일합니다. 수동 구현을 따르면 얻을 수있는 이점이 없습니다.

실용적인면에서 Singleton은 논란의 여지가 많은 패턴입니다. 주로 다음과 같은 이유 때문입니다.

  • 과도하게 사용되었습니다. 초보자 프로그래머는 싱글 톤을 다른 패턴보다 더 쉽게 이해했다. 그런 다음 Singleton을 사용하지 않고도 문제를 더 잘 해결할 수 있더라도 새로운 지식을 어디서나 적용 할 수 있습니다 (해머를 잡고있을 때 모든 것이 못처럼 보입니다).
  • 프로그래밍 언어에 따라 밀폐되지 않은 방식으로 싱글 톤을 구현하는 것은 타이타닉 한 작업으로 입증 될 수 있습니다. ). C ++에서 "결정적인"싱글 톤 구현을 검색해 보자. 나는 당신을 감히한다.
  • Singleton을 코딩 할 때와 액세스 할 코드를 작성할 때 프로그램 변수로 수행하려는 작업에 대한 몇 가지 자체 제약 조건을 수행하지 않고도 수행 할 수있는 작업 부하를 부과합니다.

마지막 결론으로 싱글 톤은 괜찮습니다. 싱글 톤을 전혀 사용하지 않는 것도 대부분의 경우에도 좋습니다.


2

당신의 해석은 정확합니다. 싱글 톤은 그 자리를 차지하지만 과용되었습니다. 정적 멤버 함수에 액세스하는 것만으로도 충분합니다 (특히, 시간 구성을 제어 할 필요가없는 경우). 더 나은 방법은 네임 스페이스에 일부 무료 함수와 변수를 넣는 것입니다.


2

프로그래밍 할 때 "올 바르고"잘못된 것이 없습니다. "좋은 습관"과 "나쁜 습관"이 있습니다.

싱글 톤은 일반적으로 나중에 재사용하기 위해 클래스로 생성됩니다. 프로그래머가 자정에 술에 취해 코딩하면서 실수로 두 인스턴스를 인스턴스화하지 않는 방식으로 작성해야합니다.

두 번 이상 인스턴스화 해서는 안되는 간단한 작은 클래스가 있으면 단일 클래스 로 만들 필요 가 없습니다 . 당신이 할 경우 그것은 단지 안전망입니다.

전역 객체를 갖는 것이 항상 나쁜 습관 은 아닙니다 . 전 세계 어디에서나 항상 사용한다는 것을 알고 있다면 몇 가지 예외 중 하나 일 수 있습니다. 그러나 글로벌은 일반적으로 나쁜 습관과 동일한 방식으로 "나쁜 습관"으로 간주됩니다 goto.


2

나는 이것을 전혀 지적하지 못한다. 연결 문자열이 생성자에 대한 매개 변수로 사용되는 방식으로 클래스를 구현하고 PDO 객체 목록 (유일한 연결 문자열마다 하나씩)을 유지 한 경우 이점이있을 수 있지만 단일 항목의 구현은 이 사례는 무의미한 운동처럼 보입니다.


1

내가 볼 수있는 한, 당신은 아무것도 빠지지 않았습니다. 예는 꽤 결함이 있습니다. 싱글 톤 클래스에 비 정적 인스턴스 변수가 있으면 차이가 생깁니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.