2010-08-18 7 views
3

다음과 같이 추상 Catalog 클래스가 있습니다. 제공된 위치 유형을 기반으로 특정 콘크리트 카탈로그를 반환하는 데 사용되는 정적 메서드 OpenCatalog()가 있습니다. 카탈로그의 유형을 결정하면 올바른 콘크리트 카탈로그 유형의 특정 OpenCatalog() 메소드를 호출합니다. 예를 들어 SQL 데이터베이스에 저장된 카탈로그 나 파일 시스템에 저장된 카탈로그를 구현할 수 있습니다. 아래 코드를 참조하십시오.정적 방법을 숨기시겠습니까?

public abstract class Catalog 
{ 
    public static ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 

     if(location is filePath) 
     { 
      return FileSystemCatalog.OpenCatalog(string location, bool openReadOnly); 
     } 
     else if(location is SQL server) 
     { 
      return SqlCatalog.OpenCatalog(string location, bool openReadOnly); 
     } 
     else 
     { 
      throw new ArgumentException("Unknown catalog type","location"); 
     } 
    } 

    ... 

} 

public abstract class FileSystemCatalog:Catalog 
{ 

    public static new ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 
     //Deserializes and returns a catalog from the file system at the specified location 
    } 

    ... 

} 



public abstract class SqlCatalog:Catalog 
{ 

    public static new ICatalog OpenCatalog(string location, bool openReadOnly) 
    { 
     //creates an returns an instances of a SqlCatalog linked to a database 
     //at the provided location   
    } 

    ... 

} 

처음으로 일반적으로 정적 방법을 숨기시겠습니까? 나는 그것이 가능하다는 것을 알고 있지만, 너무 자주해서는 안되는 것처럼 보입니다. 또한 정적 메서드를 숨기는 것이 좋은 경우 나 유효한 작업을 수행 할 수있는 유효한 예제입니까?

답변

2

abstract factory을 매우 어색하게 만드는 것처럼 보입니다. 실제로 발생하는 것은 사용자가 Single Responsibility Principle을 위반하고 카탈로그 생성 우려를 카탈로그 관심사와 혼합하는 것입니다. 당신이해야 할 일은 CatalogFactory 비 정적 클래스로 만드는 것입니다. 이것은 당신이 나중에 무엇을 하든지간에 유연성을 제공합니다 (예 : Dependency Injection).

public class CatalogFactory { 
    public ICatalog CreateCatalog(string location, bool openReadOnly) 
    { 

    if(location is filePath) 
    { 
     return OpenFileCatalog(string location, bool openReadOnly); 
    } 
    else if(location is SQL server) 
    { 
     return OpenSqlCatalog(string location, bool openReadOnly); 
    } 
    else 
    { 
     throw new ArgumentException("Unknown catalog type","location"); 
    } 
    } 
    FileSystemCatalog OpenFileCatalog(string location, bool openReadOnly) { 
    return new FileSystemCatalog{/*init*/}; 
    } 
    SqlCatalog OpenSqlCatalog(string location, bool openReadOnly) { 
    return new SqlCatalog{/*init*/}; 
    } 

} 
+0

알았어. 항상 각 구체적인 카탈로그 유형의 생성자를 직접 호출하지는 않겠지 만. 예를 들어 내 FileSystemCatalog가 열리면 XML 파일에서 DataContractSerializer를 통해 deserialize됩니다. 실제로 생성자를 호출하는 것은 DataContractSerializer입니다. 따라서 정적 메서드가 필요합니다. 여기서 aDataContractSerializer를 인스턴스화하고 파일에서 카탈로그를 deserialize하려고 시도 할 수 있습니다. –

+0

네, 괜찮아요, 그냥 삽화를 위해'새로운 FileSystemCatalog'를 넣었습니다. 또한이 메소드가'Catalog' 이외의 클래스에있는 것이 아니라 메소드가 정적 일 필요가 없으므로 단위 테스트에서 조롱 될 수 있습니다. –

0

"코드 냄새"측면에서 개인/내부 정적 메서드 사용에 대한 논쟁을 결코 발견하지 못했습니다.

실용적인 예는 해당 라이브러리 내에서만 확장하려는 일종의 서비스/유틸리티 라이브러리 내부의 확장 방법 일 수 있습니다. 당신은 기본 클래스 버전을 원하는 경우에 당신은 항상

Catalog.OpenCatalog(...); 

을 할 수 있기 때문에

internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { } 
0

당신은 정말 그것을 숨기고되지 않습니다. 실제로 정적 메서드는 특정 클래스와 연결되며 가상은 아닙니다. 파생 클래스의 기본 클래스에 정의 된 정적 메서드를 호출 할 수있는 편리한 방법입니다.

관련 문제