문제

몇 년 동안 내가 참여한 프로젝트에서, 나는 나에게 매우 유용한 것으로 입증 된 디자인 패턴을 점차 진화시켰다. 나는 때때로 그것으로 조금 복음을 받아야한다고 생각하지만, 내가 시도하고 그것이 누군가의 오래된 모자의 버전이라는 것을 알게되면 약간 당황 스러울 것입니다. 나는 파고 들었다 디자인 패턴 헛된 것을 찾고, 나는 그것에 대해 이야기하는 다른 사람을 가로 질러 달리지 않았지만 내 검색은 철저하지 않았습니다.

핵심 아이디어는 정의 객체 세트를 관리하는 브로커 객체를 가지고 있으며, 각 정의 객체는 일부 복잡한 속성의 가능한 값을 구성합니다. 예를 들어, engineType이있는 자동차, 비행기 및 발전기 클래스가있을 수 있습니다. 자동차는 자체 EngineType 객체를 저장하지 않으며, 엔진의 종류 (예 : 정수 또는 문자열 ID)를 표시하는 어떤 종류의 참조 키를 저장합니다. Wankelengine이라고 말하면 EngineType의 속성 또는 동작을보고 싶을 때 Wankelengine의 정의 객체에 대해 Enginetepebroker Singleton 객체에 참조 키를 전달합니다. 이 객체는 Enginetypes에 대해 아는 흥미로운 것을 캡슐화 할 수 있습니다.

따라서 촉진하는 것은 일종의 공유하고 느슨하게 결합 된 집계입니다. 여기서 많은 자동차에는 wankelengine이있을 수 있지만 Wankelengine 정의 객체는 하나뿐입니다 (Enginetypebroker는 해당 객체를 대체하여 느슨한 커플 링을 향상된 런타임 모파로 활용할 수 있습니다).

이 패턴의 일부 요소를 사용 할 때 (예제로 EngineType을 계속 사용) :

  1. 주어진 값이 EngineType에 대한 유효한 참조 키인지를 결정하고 참조 키에 각각 대응하는 EngineType 정의 객체를 검색하기 위해 항상 isengineType (x) 및 engineType (X) 함수가 있습니다.
  2. 나는 항상 주어진 engineType에 대해 여러 형식의 참조 키를 허용합니다. 항상 문자열 이름과 정의 객체 자체, 종종 정수 ID가 아니라 EnginEtype을 집계하는 객체 유형이 더 많습니다. 이를 통해 디버깅에 도움이되고 코드를보다 유연하게 만들고 특정 상황에서는 이전 관행에 비해 많은 후진 호환성 문제가 완화됩니다. (이 프로젝트의 맥락에서 사람들 이이 모든 일을 수행했던 일반적인 방법은 engineType가 가질 수있는 각 속성에 대한 해시를 정의하고 참조 키로 속성을 찾는 것이 었습니다.)
  3. 일반적으로 각 정의 인스턴스는 해당 정의 유형에 대한 일반 클래스의 서브 클래스입니다. 정의 객체에 대한 클래스 파일은/def/enginetype와 같은 디렉토리에 보관됩니다 (예 : Wankelengine의 클래스는/def/enginetype/wankelengine). 따라서 관련 정의는 함께 그룹화되며 클래스 파일은 EngineType의 구성 파일과 유사하지만 코드를 정의하는 기능 (일반적으로 구성 파일에서는 찾을 수 없습니다).

일부 사소한 예시적인 샘플 의사 코드 :

class Car {

    attribute Name;
    attribute EngineTypeCode;

    object GetEngineTypeDef() {
        return EngineTypeBroker->EngineType(this->GetEngineTypeCode());
    }

    string GetDescription() {
        object def = this->GetEngineTypeDef();
        return "I am a car called " . this->GetName() . ", whose " .
            def->GetEngineTypeName() . " engine can run at " .
            def->GetEngineTypeMaxRPM() . " RPM!";
    }

}

그래서 이것에 대한 이름이 있습니까?

도움이 되었습니까?

해결책

Singletonregistry

나를 믿거 나 말거나. 나는 오늘 아침에 똑같은 것을 생각하고 있었다.

나는 이전 에이 패턴을 사용했지만 그것에 대한 참조를 찾지 못하거나 이름을 지정하는 방법을 알지 못했습니다.

나는 인스턴스가 어딘가에 저장되고 키를 사용하여 얻는 일종의 "키"싱글 톤이라고 생각합니다.

마지막으로 사용하면 다른 소스에서 데이터를 검색하는 것이 었습니다.

약 50 개의 데이터베이스 테이블 (10 개)을 가지고 있었고 데이터를 표시 할 프론트 엔드 "테이블"이 있지만 데이터는 해당 소스에서 나올 수 있으며 각각은 다른 논리가 필요합니다 (쿼리, 조인, 키 , 등. )

이 프론트 엔드는 "구성 가능"이므로 어떤 값이 표시되어야하는지 알 수 없었습니다.

솔루션은 열 이름 (프론트 엔드)을 키로 가져 와서 올바른 인스턴스를 가져 와서 올바른 쿼리를 작성하는 것이 었습니다.

이것은 처음에 해시 맵에 설치되었으며 나중에 데이터베이스 테이블에서 검색되었습니다.

코드는 다음과 같습니다.

class DataFetcher {
    abstract Object getData( Object id );
}

class CustomerNameDataFetcher extends DataFetcher {
    Object getData( Object customerId ) { 
        // select name from customer where id = ? 
     }
}

class CompanyAdressDataFetcher extends DataFetcher { 
     Object getData( Object customerId ) { // don't ask why.
          // select name from company , customer where customer.co = company.co and cu = ?  etc.
     }
} 

class ProductColor extends DataFetcher { 
     Object getData( Object x ) { 
     // join from customer to color, to company to season to a bunch of table where id = ? 
}

// And the list goes on.

각 서브 클래스는 다른 논리를 사용했습니다.

런타임에 사용자는보기를 구성하고보고 싶은 것을 선택했습니다.

사용자가 볼 열을 선택했을 때 열 이름과 ID를 사용하여 데이터를 가져 왔습니다.

DataFetchers는 모두 학부모 클래스에 설치되었습니다 (이를 위해 분리 된 클래스를 갖고 싶지 않았습니다).

class DataFetcher {
    abstract Object getData( Object id );

    private static final Map fetchers = new HashMap();static { 
        fetchers.put("customer.name", new CustomerNameDataFetcher() );
        fetchers.put("company.address", new CompanyAdressDataFetcher () );
        fetchers.put("product.color", new ProductColor () );
        ...
    }
    public static DataFetcher getFetcher( String id ) { 
        return fetchers.get( id );
    }      

}

결국 프론트 엔드 테이블을 채우기 위해 나는 이것을 다음과 같이 부릅니다.

의사 코드

 for each row in table 
      for each column in row
          column.text = DataFetcher.getFetcher( column.id ).getData( row.id )
       end
 end

이렇게? 아니면 나는 당신의 설명을 잘못 읽고 내 것은 상당히 다릅니다.

마침내 나는 이것을 SingletonRegistry 또는 그와 비슷한 것으로 생각합니다. 나는 당신처럼 이것을 필요로하지 않았을 것입니다. 이것이 일반적인 패턴 일 가능성이 있습니다.

다른 팁

나는 이전과 비슷한 패턴을 이전, 가장 자주 게임에서 사용했습니다. 나는 무기 정의와 무기 인스턴스 수업을 가질 수 있습니다 (그 이름과는 관련이 없습니다). 무기 정의 클래스 (및 다양한 하위 클래스, 내가 다른 유형의 무기를 가지고 있다면, 예를 들어, 근접 대 발사체)는 해당 유형의 무기 (화재, 최대 탄약, 이름 등)에 대한 글로벌 데이터를 추적 할 책임이 있으며 모든 논리. 무기 인스턴스 클래스 (및 서브 클래스)에는 발사 순서 (화재 속도 비율을 비교하는 데 사용), 현재 탄약 수 및 포인터 (예에서와 같이 관리자 클래스에 대한 키가 될 수 있지만)가 포함됩니다. 그것은 무기 정의에 대한 패턴의 요구 사항이 아닌 것 같습니다. 무기 인스턴스에는 무기 정의 인스턴스에서 적절한 방법을 호출하여 인수로 전달하는 발사, 재 장전 등에 대한 다양한 기능이 있습니다. 이것은 게임 세계의 모든 탱크/군인/비행기에 대해 무기 정의 물건이 침착되지 않지만 모두 자신의 탄약 수 등을 가지고 있음을 의미합니다.

나는 그것이 무엇이라고 부르는지 전혀 모른다. 그리고 그것이 당신이 말하는 것과 똑같은지 확실하지 않지만 그것이 가까워 졌다고 생각합니다. 확실히 유용합니다.

GOF 빌더, 프로토 타입 및 아마도 페더급의 조합처럼 들립니다.

다양한 플라이급처럼 들립니다 (많은 자동차는 Wankelengine을 공유합니다). 그러나 그것은 어떻게 의미가 있습니까? 대부분의 자동차에는 엔진이 있지만 엔진과 동일한 인스턴스를 어떻게 가질 수 있습니까? 그들은 그렇게 멀지 않을 것입니다. 아니면 많은 자동차에 Wankelengine 유형의 엔진이 있다는 것을 의미합니까? 더 의미가있는 스포츠. 그렇다면 "WankelEngine 정의 객체"의 사용은 무엇입니까? 그 객체의 맛을 건축하고 요청자에게 전달하는 공장입니까? 그렇다면 정의 객체처럼 들리지 않으면 객체의 매개 변수를 채취하여 해당 객체를 작성하고 다시 제공하는 공장처럼 들립니다.

나는 여기에서 좋은 GOF 관행, 특히 당신이 상속하는 대신 작곡하고 있다는 것을 알 수 있습니다 (내 자동차에는 엔진이 있습니다. 내 자동차의 엔진은 Wankelengine입니다). 나는 인용문을 정확하게 기억할 수 있기를 바랍니다. 그러나 그것은 "상속 중단 캡슐화"및 "상속에 대한 호의 구성"과 같은 것입니다.

나는 이것에 의해 어떤 문제가 해결되는지 궁금합니다. 나는 당신이 많은 복잡성을 추가했다고 생각하며 그러한 복잡성에 대한 필요성을 보지 못합니다. 어쩌면 내가 이해하지 못하는 당신의 언어에 특정한 것일 수도 있습니다.

GOF 녀석은 패턴을 더 큰 패턴으로 논의합니다. 특히 MVC는 세 가지 다른 패턴의 집계입니다. 당신이 그런 일을 한 것 같습니다.

페더급 선수가 싱글 톤으로 등록되는 서비스 로케이터와 비슷하게 들립니다.

당신이 가진 것은지도, 일명 사전입니다. 여러 키가 하나의 객체에 맵핑되어 독특한 트위스트가 있습니다.

왜지도인가 :

  • 열쇠를 유지하십시오
  • 키를 사용하여 일부 데이터 구조에서 값을 쿼리하십시오.

다음에서 구현을 찾을 수 있습니다.

  • STL (포함 :지도)
  • Java (가져 오기 : java.util.dictionary)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top