Nice programing

일반 인터페이스

nicepro 2021. 1. 10. 19:57
반응형

일반 인터페이스


원격 서비스에 대한 호출을 나타내는 인터페이스를 정의하고 싶다고 가정 해 보겠습니다. 이제 원격 서비스에 대한 호출은 일반적으로 무언가를 반환하지만 입력 매개 변수도 포함 할 수 있습니다. 구현 클래스가 일반적으로 하나의 서비스 메소드 만 구현한다고 가정하십시오. 위의 정보를 감안할 때 다음은 잘못된 디자인입니다 (정답이 아닙니다).

public interface IExecutesService<A,B> { public A executeService(); public A executeService(B inputParameter); } 

이제 입력 매개 변수로 원격 서비스를 실행하는 클래스로이 인터페이스를 구현한다고 가정 해 보겠습니다.

public class ServiceA implements IExecutesService<String,String> { public String executeService() { //This service call should not be executed by this class throw new IllegalStateException("This method should not be called for this class...blabla"); }  public String executeService(String inputParameter) { //execute some service } 

위와 관련하여 두 가지 질문이 있습니다.

  1. IExecutesService<A,B>인터페이스 메소드에 대해 다른 입력 매개 변수와 리턴 유형이 필요한 서브 클래스를 제공하려는 경우 제네릭 인터페이스 ( )를 사용하는 것이 좋습니까?
  2. 위 사항을 어떻게 더 잘 수행 할 수 있습니까? 즉, 공통 인터페이스 ( IExecutesService) 아래에 서비스 실행기를 그룹화하고 싶습니다 . 그러나 구현 클래스는 일반적으로 메소드 중 하나만 구현하며 IllegalStateException을 사용하는 것은 정말 추한 느낌입니다. 또한의 B 유형 매개 변수는 IExecutesService<A,B>입력 매개 변수없이 서비스를 호출하는 구현 클래스에 대해 중복됩니다. 또한 두 개의 다른 서비스 호출에 대해 두 개의 별도 인터페이스를 만드는 것은 과도하게 보입니다.

다음은 한 가지 제안입니다.

public interface Service<T,U> { T executeService(U... args); }  public class MyService implements Service<String, Integer> { @Override public String executeService(Integer... args) { // do stuff return null; } } 

유형 삭제로 인해 모든 클래스는 이들 중 하나만 구현할 수 있습니다. 이것은 적어도 중복 방법을 제거합니다.당신이 제안하는 것은 비합리적인 인터페이스는 아니지만 그것이 어떤 가치를 더하는지 100 % 확신하지 못합니다. 표준

Callable

인터페이스 를 사용하고 싶을 수도 있습니다 . 인수를 지원하지 않지만 인터페이스의 해당 부분이 최소값 (imho)을 갖습니다.


다음은 또 다른 제안입니다.

public interface Service<T> { T execute(); } 

이 간단한 인터페이스

사용 하여 구체적인 서비스 클래스의 생성자통해 인수를 전달할 수 있습니다.

public class FooService implements Service<String> {  private final String input1; private final int input2;  public FooService(String input1, int input2) { this.input1 = input1; this.input2 = input2; }  @Override public String execute() { return String.format("'%s%d'", input1, input2); } } 

나는 두 가지 다른 인터페이스를 사용합니다. 당신은 말했다

'나는 공통 인터페이스에서 내 서비스 집행 ... 그것은 또한 과잉 두 개의 서로 다른 서비스 호출에 두 개의 인터페이스를 만드는 것 ... 클래스는 이러한 인터페이스 중 하나를 구현할 그룹에 원하는'

It's not clear what is the reason to have a single interface then. If you want to use it as a marker, you can just exploit annotations instead.

Another point is that there is a possible case that your requirements change and method(s) with another signature appears at the interface. Of course it's possible to use Adapter pattern then but it would be rather strange to see that particular class implements interface with, say, three methods where two of them trow UnsupportedOperationException. It's possible that the forth method appears etc.


As an answer strictly in line with your question, I support cleytus's proposal.


You could also use a marker interface (with no method), say DistantCall, with several several sub-interfaces that have the precise signatures you want.

  • The general interface would serve to mark all of them, in case you want to write some generic code for all of them.
  • The number of specific interfaces can be reduced by using cleytus's generic signature.

Examples of 'reusable' interfaces:

 public interface DistantCall { }  public interface TUDistantCall<T,U> extends DistantCall { T execute(U... us); }  public interface UDistantCall<U> extends DistantCall { void execute(U... us); }  public interface TDistantCall<T> extends DistantCall { T execute(); }  public interface TUVDistantCall<T, U, V> extends DistantCall { T execute(U u, V... vs); } .... 

UPDATED in response to OP comment

I wasn't thinking of any instanceof in the calling. I was thinking your calling code knew what it was calling, and you just needed to assemble several distant call in a common interface for some generic code (for example, auditing all distant calls, for performance reasons). In your question, I have seen no mention that the calling code is generic :-(

If so, I suggest you have only one interface, only one signature. Having several would only bring more complexity, for nothing.

However, you need to ask yourself some broader questions :
how you will ensure that caller and callee do communicate correctly?

That could be a follow-up on this question, or a different question...


If I understand correctly, you want to have one class implement multiple of those interfaces with different input/output parameters? This will not work in Java, because the generics are implemented via erasure.

The problem with the Java generics is that the generics are in fact nothing but compiler magic. At runtime, the classes do not keep any information about the types used for generic stuff (class type parameters, method type parameters, interface type parameters). Therefore, even though you could have overloads of specific methods, you cannot bind those to multiple interface implementations which differ in their generic type parameters only.

In general, I can see why you think that this code has a smell. However, in order to provide you with a better solution, it would be necessary to know a little more about your requirements. Why do you want to use a generic interface in the first place?

ReferenceURL : https://stackoverflow.com/questions/1623480/generic-interface

반응형