2010-01-03 3 views
3

У меня есть два метода, которые делают практически то же самое, только с разными типами. Я хочу абстрагировать эту функциональность на какой-то общий метод, и я думаю, что мог бы сделать это легко в C# с делегатами, но я не знаю эквивалент в Java. Я просто показываю два метода здесь, но есть несколько (например, восемь) разных методов стиля . Вот мои методы:абстрагирование кода от двух методов в Java, возможно, использование делегатов?

public State makeGetRequest(User user, String name) { 
    Get request = Builder.getGetRequest(user, name); 
    GetResponse response = service.get(request); 
    return ResponseTypeFactory.getResponseType(response); 
} 

public State makePutRequest(User user, String name) { 
    Put request = Builder.getPutRequest(user, name); 
    PutResponse response = service.put(request); 
    return ResponseTypeFactory.getResponseType(response); 
} 

Если не может быть какой-то делегат, как вещь, что бы взять User и String (как в первой строке каждого метода), что сделало бы эту линию abstractable к универсальной методе , Однако обратите внимание, что первая строка возвращает другое значение (т. Е. Экземпляр либо Get, либо Put), и это значение используется во второй строке. Последняя строка каждого метода уже одинаков и использует полиморфизм, чтобы выяснить, какую версию getResponseType вызывать, так что все в порядке.

Одна трудность связана со второй строкой каждого метода, где мне нужно вызвать другой метод. Возможно, у меня может быть некоторый интерфейс, который реализуется как Get, так и Put, а затем потребует делегат-подобную вещь, которая принимает экземпляр этого интерфейса. Тогда, возможно, оба GetResponse и PutResponse могут реализовать другой интерфейс, и я мог бы убедиться, что есть getResponseType, который принимает экземпляр этого интерфейса.

Get и Put наследовать от общего базового класса, Request. GetResponse и PutResponse наследуют от общего базового класса, Response. Возможно, я мог бы абстрагировать эти базовые классы, а затем, вместо того, чтобы иметь разные интерфейсы, я мог бы просто использовать методы, требующие экземпляров абстрактного базового класса.

Я не очень хорошо знаком с Java, поэтому я не знаю эквивалентных способов делать то, что я сделал бы на C#. Спасибо за помощь.

Edit: вот мои идеи для того, что интерфейсы могут быть необходимы:

IRequest    IResponse 
|  \    |  \ 
Get Put  GetResponse PutResponse 

Тогда я должны были бы эти методы:

Builder.getRequest(User, String) 
=> IRequest 

service.getPut(IRequest) 
=> IResponse 

ResponseTypeFactory.getResponseType(IResponse) 
=> State 
+1

GET? ПОЛОЖИЛ? Конечно, вы воссоздаете то, что уже существует в этом пакете javax.servlet.http? – duffymo

ответ

2

Я не думаю, что это хороший способ в Java, чтобы улучшить то, что у вас есть. Вы могли бы что-то сделать с интерфейсами, но это было бы более подробным. Если ваши методы действительно всего 3 строки, я бы придерживался того, что у вас есть. Код ясен, а дублирование минимально.

+0

+1 с этими двумя 3 строками, кажется, хорошо учтен для меня. – akuhn

1

Java обычно использует интерфейсы единого метода и анонимные внутренние классы для эквивалента делегатов, но они определенно были бы слишком подробными для примеров, которые вы опубликовали.

Ваше изменение - это ответ, если вы хотите сделать свой код более универсальным. Вам нужно будет изменить метод Builder.getRequest, чтобы он принял параметр, который указывает, является ли Get или Put тем, что вам нужно (если только это не может быть выведено из параметра «пользователь» или «имя»).

На несвязанной и потенциально противоречивой ноте, вы можете рассмотреть возможность использования Dependency Injection вместо статических методов Builder и ResponseTypeFactory.

0

Вы также можете рассмотреть возможность использования заявления enum и switch.

Простой пример:

public enum RequestMethod { GET, PUT /* Add remaining here */ }; 

public State makeRequest(RequestMethod method, User user, String name) { 
    Object response; 
    switch (method) { 
     case GET: 
      response = service.get(Builder.getGetRequest(user, name)); 
      break; 
     case PUT: 
      response = service.put(Builder.getPutRequest(user, name)); 
      break; 
     // Add remaining cases here. 
    } 
    return ResponseTypeFactory.getResponseType(response); 
} 
0

Я реализовал поддержку обратного вызова/делегата в Java с помощью отражения. Детали и рабочий источник: available on my website. Это будет соответствовать тому, что вы пытаетесь сделать.

Смежные вопросы