2012-05-22 2 views
2

다른 프로그래머가 내 서비스를 사용할 때 구현 및 클래스 이름이 필요하지 않도록 API를 만들려고합니다. 이 서비스는 "항목"에 대한 다양한 작업을 수행하지만 항목에 대한 요청을 처리하는 방법에 대한 주된 기여 요인은 사용자 유형을 기반으로합니다. 지금까지 인터페이스 (Item)와 구현 서비스 (ItemService)를 보유하고 있으며 여기에서 확장 된 여러 사용자 유형 클래스 (예 : CompanyItemService)가 있습니다. 그러나유형 특정 구현을 숨기기위한 Java 제네릭?

User company = new Company(); 
//stuff 
Item item = new ItemService<Company>(company) 
item.belongsToUser(); 

: 나는 같은 호출로 내 서비스를 사용할 수 있도록하려면

public class ItemService<T extends User> extends Item { 
    User user; 
    public ItemService(User user) { 
     this.user = user; 
    } 

    @Override 
    public boolean belongsToUser() { 
     //Check all records 
    } 
} 

public class CompanyItemService<T extends Company> extends ItemService<Company> { 
    public CompanyItemService(Company user) { 
     super(user); 
    } 

    @Override 
    public boolean belongsToUser() { 
     //Check company specific records 
    } 
} 

public class User { 
    //Common user stuff 
} 

public class Company extends User { 
    //Company specific stuff 
} 

그래서 : 같은 Company으로 사용자 유형은 슈퍼 클래스가 User과 서브 클래스 인과 구조 이 작업을 수행 할 때 ItemService의 메서드가 CompanyItemService의 재정의 메서드 대신 호출됩니다. 클래스 CompanyItemService에 속해 있다는 것을 알 필요가없이이 오버라이드 메소드를 얻을 수 있습니까?

건배,

Alexei Blue.

이 모든 것에 대한 일반적인 개념은 다른 사용자 유형이 발명되었을 때 필요하다면 다른 사용자 별 서비스를 추가하여 기존 코드를 그대로 둡니다. 또한 많은 사용자 유형이있는 경우에만 API를 사용하는 사람들이 ItemService을 사용하고 나머지는 제네릭을 사용하도록 기억해야합니다.

답변

4

당신은 짧은에서 abstract factory pattern.를 사용해야합니다, 당신은 Item 개체 또는 User의 서브 클래스 인 Class 주어진에 대한 모든 가능한 ItemService 서브 클래스를 알고 정적 메서드 어딘가가 필요 올바른의 인스턴스를 반환 ItemService 하위 클래스.

Map<Class<? extends User>, Class<? extends ItemService>> services = 
    new HashMap<Class<? extends User>, Class<? extends ItemService>>() {{ 
    put(Customer.class, CustomerItemService.class); 
    put(Employee.class, EmployeeItemService.class); 
    // more... 
}}; 

그런 다음 instance() 그냥

ItemService<? extends User> instance(Class<? extends User> c) { 
    return services.get(c); 
} 
처럼 보일 수있다 : 당신이

ItemService<?> service = ItemService.instance(Customer.class); 

또는 말할 수있는 그런

public static ItemService<?> instance(Class<? extends User> c) { 
    if (c == Customer.class) 
     return new CustomerItemService(); 
    else if (c == Employee.class) 
     return new EmployeeItemService(); 
    ... 
} 

같은 즉, 무언가, 당신은지도를 만들 수

+1

나는지도 , Class > – helios

+0

답변을 주셔서 감사합니다 어니스트, 그래서 가설을 세우면 개별적으로 각각을 지정해야 할 필요가있는 독자적인 구현으로 많은 수의 사용자 유형이 있다고 가정합니다. –

+1

@AlexeiBlue - @helios가 말한 것처럼'Map'을 사용하여 클래스 쌍에 대한 데이터를 보유 할 수 있으므로 코드 자체는 작게 유지됩니다.런타임시 속성 파일에서 해당 종류의 데이터를 읽거나 런타임에 코드에서 추가 속성을 설치할 수있는'registerItemService()'메소드를 제공하는 것이 가능합니다. 간단한 타입의 if-then은 괜찮습니다. –

0

Th 전자 코드가 제대로 작동해야합니다. 당신이 ItemService의() 메소드 belongsToUser를 호출 할 경우

Item item = new ItemService<Company>(company); 

가 호출됩니다 : 당신은 ItemService의 인스턴스를 만듭니다. 메소드를 호출하려면 CompanyItemService의 인스턴스를 만들어야합니다.

+0

답변을 alexey28에게 보내 주시면 감사하겠습니다.하지만 그게 내가 숨기려고하는 것입니다. 제네릭에 대한 제 이해는 환상적이지는 않지만 이것이 많은 용도 중 하나라고 생각했습니다. –

+2

Generics는 수동으로 캐스팅하지 않는 데 도움이됩니다. float floatVal = (Float) objVal. 그리고 그 모든 것. 여기서 원하는대로 제네릭 형식을 기반으로 인스턴스를 만들 수 없습니다. 클래스 (예 : 싱글 톤) 또는 생성자 (예 : 프로토 타입)를 통해 리플렉션을 통해 호출해야하는 클래스의 키 및 값 인스턴스가있는 레지스트리가 있어야합니다. – alexey28

관련 문제