2013-06-27 3 views
0

나는 다음과 같은 인터페이스가 있습니다Java의 함수에 인터페이스 메서드를 전달하는 방법은 무엇입니까?

public interface Mapper { 

    public SomeType methodOne(HashMap<String, Object>); 

    public OtherType methodTwo(HashMap<String, Object>); 

    ... 
} 

그 다음은 호출 할 수 있습니다를하거나 다른 클래스 내에서 매개 변수로 methodOne 또는 methodTwo?

public class Other { 
    public void doSomething(HashMap<String, Object> params, ????) { 
     Mapper mapper = new ConcreteMapper(); 
     mapper.methodOne(params); 
    } 
} 

자바 리플렉션을 시도했지만 컴파일 된 시간에 HashMap<String, Object> 유형을 가져올 수 없습니다. 이 문제를 해결할 수있는 방법이 있습니까?
동기는 내가 직장에서 만난 실제 문제에서 기인합니다. 예를 들어, REST 메서드 호출마다 다른 것은 getAddressPhoneAddressPhoneType입니다. 열린 SQL 세션과 같은 잡음이 많은 단계는 Mapper을 인스턴스화하는 것이 본질적으로 동일합니다.

public Response getAddressPhone(@PathParam("acc_nbr") String accNbr, @HeaderParam("AuthToken") String authToken) { 
    SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession(); 
    Logger log = LoggerFactory.getLoggerFactory(); 
    AddressPhoneType addressPhone = null; 
    try { 
     MyAccountMapper mapper = session.getMapper(MyAccountMapper.class); 
     HashMap<String, Object> map = new HashMap<String, Object>(); 
     map.put("acc_nbr", accNbr); 
     addressPhone = mapper.getAddressPhone(map); 
     if (addressPhone == null) { 
      return Response.ok(null).status(Status.NOT_FOUND).build(); 
     } 
    } catch (Exception e) { 
     log.debug("getAddressPhone(map):" + e.getMessage()); 
     return Response.ok().status(Status.BAD_REQUEST).build(); 
    } finally { 
     session.close(); 
    } 
    return Response.ok(gson.toJson(addressPhone)).header("AuthToken", authToken).status(Status.OK).build(); 
} 

편집 나는 MySQL의 쿼리를 수행 할 MyBatis 매퍼를 사용하고, 그래서 다음과 같은 인터페이스는 MyAccountMapper라고했다. 이러한 방법의 각 SQL 쿼리의 ID로 매핑하기 때문에, 그들에 대한 정의가 없습니다 :

내 모든 웹 서비스 호출 (I는 JAX-RS를 사용하고 있습니다), 나는이를 호출 할 필요가있는 지금
public interface MyAccountMapper { 

    AddressPhoneType getAddressPhone(HashMap<String, Object> map); 

    AdminUserInfoType getAdminUserInfo(HashMap<String, Object> map); 

    DueDateInfoType getDueDateInfo(HashMap<String, Object> map); 
    .... 
} 

위의 예제에서 볼 수 있듯이 내 데이터베이스로 뭔가를 수행하는 방법은 매퍼 설정, 로거 작성과 같은 대부분의 작업은 동일합니다. 메서드 호출과 반환 형식 만 다릅니다.

+0

Java 8에서 수행 할 수있는 것처럼 보입니다. 그러나 이러한 메소드를 호출 할 수있는 '매퍼 (Mapper)'를 전달하지 않는 이유는 무엇입니까? – arshajii

+0

'methodOne'과'methodTwo'의 리턴 타입이 다른 경우 약간 어렵습니다. 하지만 'Other.doSomething' 메서드는 반환 값을 버리는 것 같습니다. –

+0

이것은 Java 8에서 사용할 수 있습니다. 이제는 다른 매개 변수로'interface'를 전달하고이 인터페이스에서 메소드를 정의하여 원하는/원하는 것을 성취해야합니다. –

답변

1

기능이 Java의 객체가 아니기 때문에 (적어도 아직은) 원하는대로 간단하게 수행 할 수 없습니다.

Other.doSomething과 같이 반환 값을 버리지 않아도된다면 인터페이스와 몇 가지 구현을 통해 작업을 수행 할 수 있습니다. 구현은 싱글 톤일 수 있습니다. 당신이 그들을 사용하고자하는 누구에게나에 발신자 중 하나를 통과 할 수 그리고

interface MethodCaller { 
    void callMethod(HashMap<String, Object> args, Mapper mapper); 
    MethodCaller methodOneCaller = new MethodCaller() { 
     @Override 
     public void callMethod(HashMap<String, Object> args, Mapper mapper) { 
      mapper.methodOne(args); 
     } 
    } 
    MethodCaller methodTwoCaller = new MethodCaller() { 
     @Override 
     public void callMethod(HashMap<String, Object> args, Mapper mapper) { 
      mapper.methodTwo(args); 
     } 
    } 
} 

:

public class Other { 
    public void doSomething(HashMap<String, Object> params, MethodCaller caller) { 
     Mapper mapper = new ConcreteMapper(); 
     caller.callMethod(params, mapper); 
    } 
} 

Other other = . . .; 
HashMap<String, Object> stuff = . . .; 
other.doSomething(stuff, MethodCaller.methodOneCaller); 
other.doSomething(stuff, MethodCaller.methodTwoCaller); 
+0

아주 좋은 예입니다! 고맙습니다. – Chan

2
public interface Method { 
    public Object invoke(Map<> params); 
} 

public void invokeTheMethod(Map<> params, Method method) { 
    // ... do common work here ... 
    Object result = method.invoke(params); 
    // ... handle result here ... 
} 

// run common invoker with Mapper.methodOne 
invokeTheMethod(params, new Method() { 
    public Object invoke(Map<> params) { 
    return mapper.methodOne(params); 
    }); 
1

음,이 하나는 구체적인 예를 주어, 반사를 사용하는 방법 중 하나를 호출 할 수있는 방법입니다 :

Mapper concreteMapper = new ConcreteMapper(); 

    Method method1 = concreteMapper.getClass().getMethod("methodOne", HashMap.class); 
    Method method2 = concreteMapper.getClass().getMethod("methodTwo", HashMap.class); 

    method1.invoke(concreteMapper, new HashMap<String, Object>()); 
    method2.invoke(concreteMapper, new HashMap<String, Object>()); 

하지만 보일러 플레이트 코드를 피하려고하면 pa 명령을 사용하는 것이 좋습니다. 튼튼한. 또는 스프링을 사용하는 경우 AOP의 좋은 사용 사례가 될 수 있습니다.

1

매퍼 팩토리가 필요하며 매퍼 인터페이스도 수정해야한다고 생각합니다.

public interface Mapper { 
    public SomeType method(HashMap<String, Object> map); 
} 

public class MapperFactory { 
    public static Mapper createMapper(some parameters here) { 
     // create a mapper according to the parameters. 
    } 
} 

// usage within another class 
public class Other { 
    public void doSomething(HashMap<String, Object> params, ????) { 
     Mapper mapper = new MapperFactory.createMapper(......); 
     mapper.method(params); 
    } 
} 
관련 문제