[디자인 모델] 5. 단일 모델 (유일한 대상)

10213 단어 디자인 모드
1. 개술:
일부 대상 은 하나만 필요 합 니 다. 예 를 들 어 스 레 드 풀 (threadpool), 캐 시 (cache), 대화 상자, 선 호 설정 과 레 지 스 트 대상, 로그 대상, 프린터, 그래 픽 카드 등 장치 의 드라이버 대상 을 처리 합 니 다.사실 이 대상 들 은 하나의 실례 만 있 으 면 여러 개의 실례 를 만 들 면 많은 문제 가 발생 할 수 있다.(정적 클래스 변수, 정적 방법 과 적당 한 접근 수정자 로 하나의 인 스 턴 스 만 존재 할 수 있 습 니 다.)
소크라테스 유도 식 대답: (헤드 퍼스트 디자인 모델 참조)
어떻게 대상 을 만 듭 니까?
new MyObject()
만약 다른 상대 가 Myobject 를 만 들 려 고 한다 면 어떻게 될까요?뉴 마 이 오 브 젝 트 다시 해도 돼 요?
네, 그럼요.
그래서 일단 한 가지 종류 가 있 으 면 우 리 는 그것 을 여러 번 실례 화 할 수 있 습 니까?
공 개 된 클래스 라면 돼 요.
그렇지 않 으 면 어떻게 될 까?
공 개 된 클래스 가 아니라면 같은 가방 안의 클래스 만 실례 화 할 수 있 지만 여러 번 실례 화 할 수 있다
이렇게 해도 돼 요?
public Myclass

{

    private Myclass(){}

}

 
 나 는 생각해 본 적 이 없 지만, 이것 은 합 법 적 인 정의 이 고, 어느 정도 일리 가 있다.
 뭐 랄 까?
 나 는 사유 가 함 유 된 구조 기 류 는 안 된다 고 생각한다.
 또 개인 적 인 구조 기 대상 을 사용 할 수 있 습 니까?
 네, Myclass 내 코드 는 이 구조 기 를 호출 할 수 있 는 유일한 코드 라 고 생각 합 니 다. 하지만 이것 은 상식 에 맞지 않 습 니 다.
 WHY?
 Myclass 의 인 스 턴 스 만 Myclass 의 구조 기 를 호출 할 수 있 지만, Myclass 를 실례 화 할 수 있 는 다른 클래스 가 없 기 때문에 이러한 인 스 턴 스 를 얻 을 수 없습니다.
 어이, 생각 이 있어.어떻게 생각 하 세 요?
public Myclass

{

  public static MyClass getInstance(){}

}

MyClass 는 정적 인 방법 이 있 습 니 다. 우 리 는 이 방법 을 이렇게 호출 할 수 있 습 니 다. MyClas. getInstance ();
 
 왜 호출 할 때 대상 이름 이 아 닌 MyCLass 클래스 이름 을 사용 합 니까?
 getInstance 는 클래스 방법 이 고 정적 인 방법 이기 때문에 클래스 이름 을 사용 해 야 합 니 다.
 재 미 있 습 니 다. 이 걸 합치 면 '여부' 가 MyClass 를 초기 화 할 수 있 습 니까?
public MyClass

{

  private MyClass(){}

  public static Myclass getInstance()

   {

        return new MyClass();

   }

}

 
물론 입 니 다. 
 자, 두 번 째 실례 화 대상 의 방식 을 생각해 낼 수 있 습 니까?
 MyClass.getInstance();
 코드 를 완성 할 수 있 습 니 다. MyClass 는 하나의 인 스 턴 스 만 생 성 되 었 습 니까?
 응, 아마 괜 찮 을 거 야...
 
단일 모드 장점
  • 앞에서 말 한 바 와 같이 단일 모드 는 메모리 에 하나의 인 스 턴 스 만 있 고 메모리 지출 을 줄 였 다.특히 한 대상 이 빈번하게 창설, 소각 해 야 할 때 창설 과 소각 의 성능 이 최적화 되 지 않 아 단일 모델 의 장점 이 매우 뚜렷 하 다.
  • 단일 모드 는 하나의 인 스 턴 스 만 생 성하 고 시스템 성능 비용 을 줄 였 습 니 다. 한 대상 이 비교적 많은 자원 을 필요 로 할 때 설정 을 읽 고 다른 의존 대상 이 생 겼 을 때 응용 시작 할 때 하나의 단일 대상 을 직접 만 든 다음 에 영구적 으로 메모리 에 머 무 르 는 방식 으로 해결 할 수 있 습 니 다.
  • 단일 모델 은 자원 에 대한 다 중 점용 을 피 할 수 있다.
  • 단일 모델 은 시스템 에서 전체적인 방문 점 을 설정 하고 자원 방문 을 최적화 하고 공유 할 수 있다.

  • 단일 모드 단점
  • 단일 모델 은 일반적으로 인터페이스 가 없고 확장 이 매우 어렵다. 코드 를 수정 하 는 것 을 제외 하고 두 번 째 경로 가 실현 되 지 않 는 다.
  • 단일 모델 은 테스트 에 불리 하 다.병행 개발 환경 에서 단일 모델 이 완성 되 지 않 으 면 테스트 를 할 수 없다.
  • 단일 사례 모델 은 단일 직책 원칙 과 충돌 된다.

  • 2. IOS 에서 의 응용
    단일 모델 은 iOS 개발 에서 많이 사용 되 었 다. 많은 Foundation, CocoaUIKit 중의 유형 은 모두 단일 모델 을 실현 했다. 예 를 들 어 응용 프로그램 자체 UIApplication, 파일 조작 류 NSFileManager, 정보 센터 NSNotificitonCenter 등 은 모두 우리 에 게 단일 모델 을 실현 해 주 었 고 우 리 는 사용 만 하면 된다.iOS 에서 단일 모드 를 사용 할 때 클래스 방법 을 사용 하고 클래스 방법 을 통 해 이 클래스 의 유일한 대상 을 되 돌려 줍 니 다.
    ios 에서 의 응용 은 주로 다음 과 같은 세 가지 방식 이 있다.
    1、
    static Singleton *instance = nil;
    
    
    
    + (Singleton *)sharedInstance
    
    {
    
        if (instance == nil) {
    
            instance = [[super allocWithZone:NULL] init];
    
        }
    
        return instance;
    
    }
    
    
    
    + (id)allocWithZone:(NSZone *)zone
    
    {
    
        return [[self sharedInstance] retain];
    
    }
    
    
    
    - (id)copyWithZone:(NSZone *)zone
    
    {
    
        return self;
    
    }
    
    
    
    - (id)retain
    
    {
    
        return self;
    
    }
    
    
    
    - (NSUInteger)retainCount
    
    {
    
        return NSUIntegerMax;  //denotes an object that cannot be released
    
    }
    
    
    
    - (void)release
    
    {
    
        //do nothing
    
    }
    
    
    
    - (id)autorelease
    
    {
    
        return self;
    
    }

    이 를 통 해 정적 구성원 을 사용 하여 영구적 으로 존재 하 는 대상 을 유지 하고 alloc 방법 alloc 방법 allocWithZone: 을 덮어 쓰 고 3、 방법 을 호출 하 며 인용 기술 과 관련 된 모든 방법 을 덮어 쓰 는 것 을 볼 수 있다. 이 는 이 대상 을 소각 하지 않 게 한다.이렇게 보면 기본적으로 우리 가 필요 로 하 는 것 을 실현 한 것 처럼 보이 지만, 쓰기 가 귀 찮 고, 또 하나의 문제 가 있다. 그것 은 바로 다 중 스 레 드 문제 이다. 만약 다 중 스 레 드 에 있다 면, 이 방법 은 하나의 대상 만 생 긴 다 는 것 을 보장 할 수 없다.그래서 이런 방식 은 소개 만 할 뿐 추천 하지 않 습 니 다.
    2. 도입 헤더 파일
    프로그래머 들 은 모두 게 으 름 을 피 우 는데, 지금 은 매크로 정 의 를 사용 하여 이 많은 일 을 해결 하 는 것 이 유행 하고, 더욱 주도면밀 하 게 고려 하 는 것 이 유행 하고 있다.
    단일 예 는 다음 과 같은 인 터 페 이 스 를 포함한다. + (MyClass*) sharedInstance; + (void) purgeSharedInstance;
    shared Instance 를 호출 하면 단일 예 를 만 들 고 되 돌려 줍 니 다.
    PurgeShared Instance 를 호출 하면 단일 예 를 소각 합 니 다.
    수 동 으로 alloc 를 호출 하 는 것 도 하나의 예 라 고 보장 할 수 있 습 니 다. 이렇게 호출 할 수 있 습 니 다.
    [[MyClass alloc] initWithParam:firstParam secondParam:secondParam];
    단지 shared Instance 이전에 호출 할 수 있 도록 해 야 합 니 다. 단 한 번 의 창설 기회 가 있 기 때 문 입 니 다.
    다음은 매크로 쓰기 " 
    MyClass.h: 
    
    ======================================== 
    
        #import "SynthesizeSingleton.h" 
    
    
    
        @interface MyClass: SomeSuperclass 
    
        { 
    
            ... 
    
        } 
    
        SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass); 
    
    
    
        @end 
    
    ======================================== 
    
    
    
    
    
        MyClass.m: 
    
    ======================================== 
    
        #import "MyClass.h" 
    
    
    
        @implementation MyClass 
    
    
    
        SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass); 
    
    
    
        ... 
    
    
    
        @end 
    
    ========================================

    소스 라 이브 러 리 다운로드 주소 iOS block 는 4.0 이후 GCDiOS 두 가지 특성 이 GCD 개발 에 큰 편 의 를 가 져 다 주 고 개발 을 더욱 흥 미 롭 게 만 들 었 다. 그렇다면 어떻게 block + dispatch_once(dispatch_once_t *predicate, ^(void)block) 를 통 해 단일 모델 을 실현 할 수 있 을 까?유형 구조 체 의 지침 은 GCD 실행 이 완료 되 었 는 지 테스트 하 는 데 사 용 됩 니 다. 이 지침 이 가리 키 는 구조 체 는 전체 적 이거 나 정적 이 어야 합 니 다. 두 번 째 매개 변 수 는 반환 값 과 매개 변수 가 모두 비어 있 는 dispatch_once_t 이 고 block 체 에서 대상 의 초기 화 를 하면 됩 니 다. block프로그램의 수명 주기 에 한 번 만 호출 될 수 있 기 때문에 다 중 스 레 드 에 도 문제 가 없 을 것 입 니 다. 이 방법 은 사용 방법:
     
    + (Singleton *)sharedInstance
    
    {
    
        static Singleton *instance = nil;
    
    
    
        static dispatch_once_t onceToken;
    
        dispatch_once(&onceToken, ^{
    
            instance = [[Singleton alloc]init];
    
        });
    
    
    
        return instance;
    
    }



    dispatch once 의 역할 은 실행 되 고 전체 프로그램의 성명 주기 에서 한 번 만 블록 대상 을 실행 하 는 것 입 니 다. 그야말로 하나의 예 를 들 어 생 긴 것 입 니 다. 그리고 프로그램 시작 에 초기 화 해 야 할 동작 도 있 습 니 다. 이 를 위해 한 번 만 실행 하면 이 dispatch once 에 넣 어 실행 할 수 있 습 니 다.
    그 다음 에 우 리 는 이 코드 블록 이 실행 되 는 지 확인 하 는 단언 이 필요 하 다 는 것 을 보 았 다. 이 단언 의 지침 은 저장 해 야 한다. 첫 번 째 방법 에 비해 지침 을 하나 더 저장 해 야 한다.
     
    방법 소개 에서 분명히 말 했다. 응용 프로그램 에서 전체 데이터 대상 (단일 모드) 을 초기 화 하 는 데 유용 하 다.
    다 중 스 레 드 에서 동시에 호출 하면 이 함 수 는 이 block 호출 이 끝 날 때 까지 동기 화 를 기다 릴 것 입 니 다.
    이 단언 의 지침 은 전역 적 으로 저장 하거나 정적 영역 에 두 어야 합 니 다. 자동 분배 영역 이나 동적 영역 에 저 장 된 단언 을 사용 하면 dispatch once 가 실행 하 는 결 과 는 예측 할 수 없습니다.
     
    요약: 1. 이 방법 은 단일 예 나 초기 화 동작 을 만 들 때 사용 할 수 있 습 니 다. 유일 성 을 보장 합 니 다. 2. 이 방법 은 스 레 드 가 안전 하 므 로 안심 하고 과감하게 하위 스 레 드 에서 사용 하 십시오. (전 제 는 dispatch once t 입 니 다. onceToken
    대상 은 전체 또는 정적 대상 이 어야 합 니 다. 이 점 은 매우 중요 합 니 다. 이 점 을 보장 하지 못 하면 이 방법 이 한 번 만 실 행 될 것 이 라 고 보장 할 수 없습니다.)
     
    참고 블 로그:
    물방울 이 돌 을 뚫 고 믿음 을 지 켜 라.      --- wtlucky's Blog

    좋은 웹페이지 즐겨찾기