누구든지 플라이급 패턴을 사용하는 구체적인 예가 있습니까? [닫은]

나는 디자인 패턴을 연구하고 플라이 웨이트 패턴을 가로 질러왔다. 응용 프로그램에서 패턴을 사용할 기회를 보려고 노력했지만 패턴을 사용하는 방법을 보는 데 문제가 있습니다. 또한 다른 사람들의 코드를 읽을 때 플라이 웨이트 패턴이 사용되고 있다는 신호는 무엇입니까?

정의에 따르면 다음과 같이 말합니다.

많은 수의 세밀한 개체를 효율적으로 지원하려면 공유를 사용하십시오.

올바르게 읽으면 사전 및 해시 테이블이 플라이 가중치의 인스턴스가 될 수 있습니까?

미리 감사드립니다.



답변

한 예로 Java 라이브러리에 있습니다. Java는 기본 유형 (예 : int32 비트 정수)과 랩퍼 (예 : Integer랩핑 int)를 갖 습니다 . 이 “상자”는에 방법이 있습니다 int에은 Integer과를 언 박싱 Integerint. 래퍼는 프리미티브 유형이 객체가 아니므로 Maps의 키로 사용 하거나 s에 배치 할 수 없기 때문에 필요합니다 Collection.

복싱 방법은 -128에서 127 사이의 값에 Integer해당 하는 일종의 캐시로 flyweight 객체 배열을 사용합니다 int.이 값은 키로 사용되거나 컬렉션에 배치 될 가능성이 가장 높은 값이므로 할당 및 메모리 사용이 줄어 듭니다. ( Integer0 주위에 떠있는 값을 나타내는 5000000이 있으면 플라이급 인스턴스를 재사용하는 것보다 5000000 배 많은 메모리를 사용합니다).


답변

제도법. 일반적으로 래스터 이미지 (대부분의 소비자 수준 컴퓨터 그래픽의 중추)는 CPU를 많이 사용하지만 메모리 비용이 많이 듭니다 (메모리가 저렴하지만 CPU가 비싸기 때문에 괜찮습니다). 더 큰 UI (Windows GUI 앱의 아이콘에서 워드 프로세서의 글꼴 문자, 3D 게임의 표면 질감에 이르기까지)를 렌더링 할 때 해당 래스터 이미지를 여러 번 반복해야하는 경우에는 이치에 맞습니다. 이미지를 메모리에 한 번로드 한 다음 저렴하고 자체적으로 많은 메모리를 차지하지 않는 매우 간단한 객체를 사용하여 이미지를 가리 킵니다. 이미지가 표시되어야하는 그래픽 공간의 한 지점 인 스프라이트는 3D 포인트 일 뿐이며 사용할 이미지의 첫 번째 픽셀에 대한 메모리 포인터입니다. 스프라이트 이미지 파일 부분의 크기를 포함 할 수도 있습니다. 그래픽 또는 메모리 용어로. 이 정보는 스프라이트의 이미지 또는 위치를 변경하는 등 변경하기에 매우 저렴하며 매번 새 이미지를로드하지 않고도 수행 할 수 있으므로 기본 프로그램의 적절한 부분을 조작하고 표시하는 기본 프로그램의 성능이 크게 향상됩니다. 완전한 UI “장면”을 렌더링하기위한 적절한 이미지.


답변

Character스몰 토크의 ASCII 범위 인스턴스는 플라이 웨이트입니다.

때이 같은 평가 Character space, Character class >> #value:이 실행을 :

value: anInteger
    "Answer the Character whose value is anInteger."

    anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
    ^ CharacterTable at: anInteger + 1.

클래스 변수 CharacterTable는 다음과 같이 초기화됩니다.

initialize
    "Create the table of unique Characters, and DigitsValues."
    "Character initializeClassificationTable"

    CharacterTable ifNil: [
        "Initialize only once to ensure that byte characters are unique"
        CharacterTable := Array new: 256.
        1 to: 256 do: [:i | CharacterTable
            at: i
            put: (self basicNew setValue: i - 1)]].
    self initializeDigitValues

따라서 문자열을 만들 때 ASCII 범위 CharacterCharacterTable매번 새로 작성되지 않고 발생합니다.


답변

플라이급 패턴을 사용하는 목적은 불필요한 객체 초기화를 피하여 공간을 절약하는 것입니다. GOF 에 의해 정의 된 것처럼 객체는 내재 상태와 외재 상태의 두 가지 상태를 가질 수 있습니다.

  • 고유 상태 : 플라이급에 저장됩니다. 플라이급 상황과 독립적 인 정보로 구성되어 공유 할 수 있습니다.
  • 외부 상태 : 플라이급의 상황에 따라 달라 지므로 공유 할 수 없습니다. 클라이언트 객체는 외부 상태를 필요할 때 플라이급으로 전달합니다.

각 열에 모든 텍스트 행이 포함되고 행에 문자가 포함될 수있는 간단한 텍스트 편집기 응용 프로그램을 개발한다고 가정합니다.

여기서 딜레마는 Character 클래스를 디자인하는 방법입니다. char c문자 클래스 내에서 메인 (고유 상태) 객체이어야한다. 그러나 문자는 글꼴 및 크기 (외부 상태)를 가질 수 있습니다. 따라서 외부 상태를 Row (클라이언트)에 저장하고 필요할 때 액세스해야합니다. 이를 위해 글꼴과 크기를 저장하는 두 개의 목록이 작성됩니다.

Flyweight 패턴을 따라 문자를 재사용 할 수 있으며 모든 ASCII 기호 ( Character개체) 를 포함하는 특정 개체 목록 (flyweight pool)에서 개체를 참조하고 있습니다.

다음은 시각적으로 설명한 내용입니다.

‘hello’를 인쇄 Character하려면 5 대신 4 개의 개체 만 필요합니다. 글꼴이 변경되면 새 개체가 필요하지 않습니다. 이 점에 유의 하지 않을 것이다 가능한 우리는, 예를 들어, 문자 클래스의 외부 상태를 저장했다

class Character
{
    char c;
    int Size;
    Font font;

    ....
}

큰 데이터 세트에이 패턴을 적용 하면 응용 프로그램의 메모리 복잡성과 개체 재사용 성 이 크게 최적화 됩니다.