나는 자산 관리자 에 대해 생각하지 않고 시작합니다 . "관리자"와 같이 느슨하게 정의 된 용어로 아키텍처를 생각하면 양탄자 아래에서 많은 세부 사항을 정신적으로 쓸어 버리게되어 결과적으로 솔루션을 결정하기가 더 어려워집니다.
기본 요구 사항 저장소를 추상화하고 지원되는 유형 집합을 확장 할 수있는 리소스로드 메커니즘을 만드는 것과 관련이있는 것처럼 보이는 특정 요구에 집중하십시오. 예를 들어 이미로드 된 리소스의 캐싱과 관련하여 실제로는 아무것도 없습니다. 단일 책임 원칙에 따라 자산 캐시를 별도의 엔터티로 구축하고 다른 두 인터페이스를 집계해야 하기 때문에 좋습니다. , 적절한.
특정 관심사를 해결하려면 로더가 자산 자체를로드하지 않고 특정 유형의 자산로드에 맞게 조정 된 인터페이스에 책임을 위임하도록 로더를 설계해야합니다. 예를 들면 다음과 같습니다.
interface ITypeLoader {
object Load (Stream assetStream);
}
스트림에서 특정 유형의 데이터를로드하도록 각 새 클래스를 조정하여이 인터페이스를 구현하는 새 클래스를 작성할 수 있습니다. 스트림을 사용하면 형식 로더를 일반적인 스토리지에 구애받지 않는 인터페이스에 대해 쓸 수 있으며 디스크 나 데이터베이스에서로드하기 위해 하드 코딩 할 필요가 없습니다. 이를 통해 네트워크 스트림에서 에셋을로드 할 수도 있습니다 (게임이 콘솔에서 실행되고 편집 도구가 네트워크에 연결된 PC에서 실행될 때 에셋의 핫 리로드를 구현하는 데 매우 유용 할 수 있음).
기본 자산 로더는 다음 유형별 로더를 등록하고 추적 할 수 있어야합니다.
class AssetLoader {
public void RegisterType (string key, ITypeLoader loader) {
loaders[key] = loader;
}
Dictionary<string, ITypeLoader> loaders = new Dictionary<string, ITypeLoader>();
}
여기에 사용 된 "키"는 원하는 것이 될 수 있으며 문자열 일 필요는 없지만 시작하기 쉽습니다. 이 키는 사용자가 특정 자산을 식별하는 방법을 고려하여 적절한 로더를 찾는 데 사용됩니다. 구현시 파일 시스템이나 데이터베이스를 사용하고 있다는 사실을 숨기고 싶기 때문에 파일 시스템 경로 또는 이와 유사한 방식으로 자산을 참조하는 사용자를 가질 수 없습니다.
사용자는 최소한의 정보가있는 자산을 참조해야합니다. 어떤 경우에는 파일 이름만으로 충분하지만 유형 / 이름 쌍을 사용하는 것이 바람직하므로 모든 것이 매우 명확합니다. 따라서 사용자는 애니메이션 XML 파일 중 하나의 명명 된 인스턴스를로 참조 할 수 있습니다 "AnimationXml","PlayerWalkCycle"
.
여기에 AnimationXml
등록한 키 AnimationXmlLoader
가 구현 IAssetLoader
됩니다. 분명히 PlayerWalkCycle
특정 자산을 식별합니다. 유형 이름과 리소스 이름이 주어지면 자산 로더는 해당 자산의 원시 바이트에 대한 영구 저장소를 쿼리 할 수 있습니다. 여기에서 최대한의 일반성을 얻으려고 할 때 로더에 스토리지 액세스 수단을 작성할 때이를 전달하여 나중에 스트림을 제공 할 수있는 것으로 대체 할 수 있습니다.
interface IAssetStreamProvider {
Stream GetStream (string type, string name);
}
class AssetLoader {
public AssetLoader (IAssetStreamProvider streamProvider) {
provider = streamProvider;
}
object LoadAsset (string type, string name) {
var loader = loaders[type];
var stream = provider.GetStream(type, name);
return loader.Load(stream);
}
public void RegisterType (string type, ITypeLoader loader) {
loaders[type] = loader;
}
IAssetStreamProvider provider;
Dictionary<string, ITypeLoader> loaders = new Dictionary<string, ITypeLoader>();
}
매우 간단한 스트림 제공자는 지정된 자산 루트 디렉토리에서 이름이 지정된 서브 디렉토리 를 찾고 스트림으로 type
이름 지정된 파일의 원시 바이트를로드하여 name
리턴합니다.
간단히 말해서, 여기에있는 것은 다음과 같은 시스템입니다.
- 어떤 종류의 백엔드 스토리지 (디스크, 데이터베이스, 네트워크 스트림 등)에서 원시 바이트를 읽는 방법을 알고있는 클래스가 있습니다.
- 원시 바이트 스트림을 특정 종류의 리소스로 변환하여 반환하는 방법을 알고있는 클래스가 있습니다.
- 실제 "자산 로더"에는 위의 모음이 있으며 스트림 제공자의 출력을 유형별 로더로 파이프하여 콘크리트 자산을 생성하는 방법을 알고 있습니다. 스트림 제공자 및 유형별 로더를 구성하는 방법을 노출함으로써 실제 자산 로더 코드를 수정하지 않고도 클라이언트 (또는 사용자)가 확장 할 수있는 시스템이 있습니다.
몇 가지주의 사항 및 최종 참고 사항 :
위의 코드는 기본적으로 C #이지만 최소한의 노력으로 거의 모든 언어로 번역해야합니다. 이를 용이하게하기 위해 오류 확인이나 올바르게 사용하는 IDisposable
것과 다른 언어로 직접 적용되지 않는 다른 관용구를 많이 생략했습니다 . 그것들은 독자에게 숙제로 남아 있습니다.
마찬가지로 object
위와 같이 콘크리트 자산을 반환 하지만 원하는 경우 제네릭이나 템플릿 또는 더 구체적인 객체 유형을 생성하는 데 사용할 수 있습니다 (작업해야합니다).
위와 같이, 나는 여기서 캐싱을 다루지 않습니다. 그러나 동일한 종류의 일반 성과 구성 가능성으로 캐싱을 쉽게 추가 할 수 있습니다. 사용해보십시오!
이 작업을 수행하는 방법은 많고 많으며, 방법이 없거나 합의가 없기 때문에 찾을 수 없었습니다. 이 답변을 고통스럽게 긴 코드로 변환하지 않고 특정 지점을 가로 질러 충분한 코드를 제공하려고했습니다. 이미 너무 오래되었습니다. 궁금한 점이 있으면 언제든지 의견을 말하거나 채팅 에서 나를 찾으십시오 .