English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 디자인 패턴의 싱글턴 패턴을 전면 분석

이 문서는 Java 디자인 패턴의 단例 모델의 구체적인 코드를 공유하여 참고하는 데 도움이 되도록 하였습니다. 구체적인 내용은 다음과 같습니다

개념:

단例 모델: 한 클래스에 하나의 인스턴스만 있습니다.

한 클래스는 하나의 인스턴스만 가지고 있으며, 전체 접근점을 제공합니다.

이 모델을 사용하는 이유:

  웹사이트를 브라우징하는 동안, 일부 웹사이트는 "현재 온라인 인원수"를 표시합니다. 이 기능을 구현하기 위해 일반적으로 로그인한 각 IP를 메모리, 파일 또는 데이터베이스에 저장하고, IP가 하나 더 많아지면 "+1일반적으로 메서드를 사용하여 구현합니다. 예를 들어, add() 메서드를 사용합니다.+1함수를 사용하는 예, 'update' 문을 통해 데이터베이스에 저장된 데이터를 먼저 가져와서+1데이터베이스에 데이터를 업데이트하고, 저장한 후, 페이지에 표시할 때 다른 메서드를 통해 데이터베이스에 저장된 데이터를 다시 가져옵니다. 그러나, 여러 사용자가 동시에 로그인할 때, 각 사용자가 객체를 new하여 '객체.메서드이름'을 통해 add() 메서드를 호출하고 데이터를 데이터베이스에 저장하면, 여러 사용자가 실제 사용자 데이터를 정확하게 데이터베이스에 기록할 수 없게 됩니다. 따라서, 이 카운터를 전역 객체로 설계하면(모든 사람이 이 객체를 사용하고, new를 사용하지 않음), 모든 사람이 공유하는 동일한 데이터를 사용할 수 있어서 이러한 문제를 피할 수 있습니다. 이것이 우리가 말하는 단일 모델의 한 가지 응용입니다. 

동일하게, 다른 상황에서도 유사한 상황을 만나고 유사한 아이디어를 사용할 수 있습니다. 예를 들어:

   1. 외부 자원: 각 컴퓨터에는 여러 개의 프린터가 있지만, 두 개의 프린트 작업이 동시에 프린터로 출력되지 않도록 한 PrinterSpooler가 하나만 있습니다. 내부 자원: 대부분의 소프트웨어는 시스템 구성을 저장하기 위한 한 개(또는 여러 개)의 속성 파일을 가지고 있으며, 이러한 시스템은 이러한 속성 파일을 관리하는 객체가 하나가 되어야 합니다.
   2. Windows의 태스크 관리자(태스크 관리자)는 매우 표준적인 단일 모델입니다(이렇게 익숙한 것 같은데). 생각해 보세요, 두 개의 Windows 태스크 관리자를 열 수 있을까요? 믿지 않으시다면 직접 시도해 보세요~
   3. Windows의 리쿨릭 버닝(리쿨릭 바인드)은 매우 표준적인 단일 모델 애플리케이션입니다. 전체 시스템 실행 중 리쿨릭 바인드는 유일한 인스턴스를 유지합니다.
   4. 웹 사이트의 카운터는 일반적으로 단일 모델을 사용하여 구현됩니다. 그렇지 않으면 동기화가 어렵습니다.
   5. 애플리케이션의 로그 애플리케이션은 일반적으로 단일 모델을 사용하여 구현됩니다. 이는 공유 로그 파일이 항상 열려 있기 때문입니다. 여러 개의 인스턴스가 동시에 작업을 수행하면 내용이 추가되지 않습니다.
   6. 웹 애플리케이션의 설정 객체의 읽기는 일반적으로 단일 모델을 사용합니다. 이는 설정 파일이 공유 자원이기 때문입니다.
   7. 데이터베이스 커넥션 풀 디자인은 일반적으로 단일 모델을 사용합니다. 이는 데이터베이스 커넥션이 데이터베이스 자원이기 때문입니다. 데이터베이스 소프트웨어 시스템에서 데이터베이스 커넥션 풀을 사용하는 주요 목적은 데이터베이스 커넥션을 열거나 닫는 데 발생하는 효율성 손실을 절약하는 것입니다. 이 효율성 손실은 매우 비싸며, 단일 모델을 사용하여 이러한 손실을 크게 줄일 수 있습니다.
   8. 멀티 스레드의 스레드 풀 디자인은 일반적으로 단일 모델을 사용합니다. 이는 스레드 풀에서 스레드를 쉽게 제어하기 위해서입니다.
   9. 파일 시스템이操作系统의 파일 시스템이며, 대형의 단일 모델 구현의 실제 예시입니다. 하나의操作系统은 하나의 파일 시스템만 있습니다.
   10. HttpApplication도 단일 인스턴스의 유형적인 응용입니다. ASP.Net(IIS) 전체 요청 라이프 사이클을 잘 알고 있는 사람들은 HttpApplication도 단일 모드라고 알 수 있습니다. 모든 HttpModule은 하나의 HttpApplication 인스턴스를 공유합니다. 

결론적으로, 단일 모드의 일반 응용 시나리오는 다음과 같습니다:

    1. 자주 생성하고 파괴하는 필요한 객체.

    2. 객체를 생성할 때 시간이 많이 소요되거나 자원이 많이 소모되지만 자주 사용되는 객체.

      3. 상태가 있는 도구 클래스 객체.

    4. 자주 데이터베이스나 파일에 접근하는 객체.

    5. 자원 공유의 경우, 자원 처리 시 발생할 수 있는 성능이나 손실 등을 피할 수 있습니다. 예를 들어, 위의 로그 파일, 애플리케이션 설정 등.

    6. 자원을 제어하는 경우, 자원 간의 상호 통신이 용이합니다. 예를 들어, 스레드 풀 등.

특징:

1、단일 클래스는 단 하나의 인스턴스만 가질 수 있습니다;

2、단일 클래스는 자신의 독특한 인스턴스를 생성해야 합니다;

3、단일 클래스는 모든 다른 객체에게 이 인스턴스를 제공해야 합니다;

단일 모드 요소: 

   1. 프라이빗 구조 메서드
   2. 자신의 인스턴스를 가리키는私有静态 참조
   3. 자신의 인스턴스를 반환하는 공개静态 메서드 

단일 모드를 구현하는 세 가지 방법:

1. 고아식: 클래스 로드 시에만 인스턴스를 구축하여 즉각 초기화.(예비 로드 방법)

/**
* 고아식(추천)
*
*/
public class Test {
    private Test() {
    }
    public static Test instance = new Test();
    public Test getInstance() {
        return instance;
    }
}

점 

    1. 스레드 안전
    2. 클래스 로드와 동시에 이미静态 객체를 생성하여 호출 시 반응 속도가 빠르다

단점 

    자원 효율성이 높지 않으며, getInstance()가 결코 실행되지 않을 수 있지만, 해당 클래스의 다른 정적 메서드를 실행하거나 클래스를 로드하면 (class.forName) 해당 인스턴스가 여전히 초기화됩니다.

2. 빈둥이식: 첫 번째 사용 시에만 인스턴스를 구축하여 지연 초기화.

class Test {
    private Test() {
    }
    public static Test instance = null;
    public static Test getInstance() {
        if (instance == null) {
       //여러 스레드가 instance이 모두 null이 아니라는 것을 판단할 때, new 작업을 수행할 때 여러 스레드가 중복이 발생할 수 있습니다.
            instance = new Singleton2()
        }
        return instance;
    }
}

점 

    어둡은 한식의 경우 사용하지 않았을 때 인스턴스를 생성하는 것을 피하고, 자원 활용률이 높으며, getInstance()를 실행하지 않으면 인스턴스가 생성되지 않으며, 해당 클래스의 다른 정적 메서드를 실행할 수 있습니다.

단점 

    빈둥이식은 단일 스레드에서 문제가 없지만, 여러 스레드가 동시에 접근할 때는 여러 개의 인스턴스를 동시에 생성할 수 있으며, 이러한 여러 개의 인스턴스는 동일한 객체가 아닙니다. 그리고 나중에 생성된 인스턴스는 먼저 생성된 인스턴스를 덮어쓸 수 있지만, 여전히 다른 객체를 받을 수 있는 상황이 발생할 수 있습니다. 이 문제를 해결하기 위해서는 synchronized을 사용하는 것이 좋습니다. 처음 로드할 때는 빠르지 않으며, 여러 스레드가 사용할 때 불필요한 동기화 비용이 큽니다.

3.더블 체크

class Test {
    private Test() {
    }
    public static Test instance = null;
    public static Test getInstance() {
        if (instance == null) {
            synchronized (Test.class) {
                if (instance == null) {
                    instance = new Test();
                }
            }
        }
        return instance;
    }
}

점 

    자원 이용률이 높으며, getInstance()를 실행하지 않으면 인스턴스가 생성되지 않으며, 이 클래스의 다른 정적 메서드를 실행할 수 있습니다

단점 

    처음 로드할 때 반응이 빠르지 않습니다. Java 메모리 모델의 일부 이유로 종종 실패합니다

4.정적 내부 클래스

class Test {
    private Test() {
    }
    private static class SingletonHelp {
        static Test instance = new Test();
    }
    public static Test getInstance() {
        return SingletonHelp.instance;
    }
}

점 

    자원 이용률이 높으며, getInstance()를 실행하지 않으면 인스턴스가 생성되지 않으며, 이 클래스의 다른 정적 메서드를 실행할 수 있습니다

단점 

    처음 로드할 때 반응이 빠르지 않습니다

결론: 

    일반적으로 굶주림 스타일을 사용하며, 자원에 매우 신경 쓰는 경우에는 정적 내부 클래스를 사용할 수 있지만, 지연된 스타일 및 더블 체크를 사용하지 않는 것이 좋습니다.

 이것이 본 문서의 모든 내용입니다. 여러분의 학습에 도움이 되길 바라며, 모두들이 나아가는 가이드를 많이 지지해 주시길 바랍니다。

고지사항: 본 내용은 인터넷에서 가져왔으며, 저작권자가 소유하고 있으며, 인터넷 사용자가 자발적으로 기여하고 자체적으로 업로드한 내용입니다.本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,请发送邮件至:notice#oldtoolbag.com(메일을 보내는 경우 #을 @으로 변경하여 신고하고, 관련 증거를 제공하시면, 사실을 확인하면 즉시 저작권 침해 내용을 삭제하겠습니다。)

추천 항목