Можно ли использовать шаблон адаптера в тех случаях, когда разные методы интерфейса имеют разные параметры - PullRequest
2 голосов
/ 15 июля 2010

Я создаю клиентское приложение Swing, в котором будут данные, предоставленные одним из многих поставщиков данных (брокеров).Однако поставщики данных могут по-разному выполнять одни и те же действия, например

метод входа в систему broker1

public boolean doLogin(String username, String password);

метод входа в систему broker2

public int login(String username, String password,String sessionId);

Для всех поставщиков установлен набордействия такие же, например

login, getstatus, sendRequest, getData, logOff
(но у них разные параметры и типы возврата)

Я посмотрел на шаблон адаптера, но, к сожалению,не в состоянии использовать его, поскольку требуемые методы имеют разные параметры.

Можно ли использовать шаблон адаптера в этом случае?если да, то как?
Если нет, то как лучше всего это сделать?

Спасибо.

Ответы [ 2 ]

3 голосов
/ 15 июля 2010

Шаблоны - это общие рекомендации (отправная точка) лучших практик. Многие разработчики «адаптируют» шаблоны к своим потребностям; Важно то, что если вы должны использовать шаблон, используйте его последовательно во всем приложении.

Теперь, чтобы ответить на ваш вопрос; да, шаблон адаптера может очень хорошо использоваться в вашей ситуации. Возможное решение (в подобном случае) может быть:

abstract class BrokerAbstract<T> {
   private int errCode;
   private String errMessage;

   abstract public boolean login(String user, String pass, Map<String,Object> options);
   abstract public int getStatus(Map<String,Object> options);
   abstract public boolean sendRequest(Map<String,Object> options);
   abstract public T getData(Map<String,Object> options);
   abstract public boolean logOff(Map<String,Object> options);

   protected void setError(int code, String message) {
      this.errCode = code;
      this.errMessage = message;
   }

   public int getErrorCode() { return this.errCode; }
   public String getErrorMessage() { return this.errMessage; }
}

Тогда

class Broker1 extends BrokerAbstract<Object> {
   private OriginalBroker1 original;       

   public boolean login(String user, String pass, Map<String,Object> options) {
      return original.doLogin(user, pass);  // ignore options
   }
   public boolean login(String user, String pass) {
      return login(user, pass, null);  // third parameters will be ignored
   }
   public int getStatus(Map<String,Object> options) { /*...*/ return 0; }
   public boolean sendRequest(Map<String,Object> options) { /*...*/ return false; }
   public Object getData(Map<String,Object> options) { 
      return original.getData();  // OriginalBroker1.getData():Object
   }
   public boolean logOff(Map<String,Object> options) {
      return original.doLogout((boolean) options.get("clearSession"));
   }
   public boolean logoff() {
      HashMap<String,Object> options = new HashMap<String,Object>();
      options.put("clearSession", true);
      return logoff(options);   // proxy to original method
   }
}

Или

class Broker2 extends BrokerAbstract<Integer> {
   private OriginalBroker2 original;       

   public boolean login(String user, String pass, Map<String,Object> options) {
      int code = original.doLogin(user, pass, (String) options.get("sessionId"));
      if (0 != code) {
          setError(code, "Custom error message"); // could use enum here for messages...
          return false;
      } else {
          return true;
      }
   }
   public boolean login(String user, String pass, String sessionId) {
      HashMap<String,Object> options = new HashMap<String,Object>();
      options.put("sessionId", sessionId);
      return login(user, pass, options);
   }
   public int getStatus(Map<String,Object> options) { /*...*/ return 0; }
   public boolean sendRequest(Map<String,Object> options) { /*...*/ return true; }
   public Integer getData(Map<String,Object> options) { 
      return original.getData(options.get("key"));  // OriginalBroker2.getData(key:String):int
   }
   public boolean logOff(Map<String,Object> options) {
      return original.doLogout();
   }
   public boolean logoff() {
      return logoff(null);   // ignore third parameter
   }
}

Конечно, это очень общий подход. Если вы знаете, что один метод будет получать строки для всех параметров, вы также можете иметь абстрактную подпись, например:

abstract public boolean login(String...args);

Тогда ваша конкретная реализация будет:

abstract class A {
   abstract public boolean login(String...args);    
}
class B extends A {
   public boolean login(String...args) { return this.login(args[0], args[1]); }
   public boolean login(String user, String pass) { return original.login(user,pass); }
}

class C {
   public void login() {
      B b = new B();
      b.login("foo", "secret");
      // or
      b.login(new String[] {"foo", "secret"});
      // or !
      b.login("foo", "secret", "sessionId");  // will ignore third, but otherwise would still work...
   }
}

и т.д.

0 голосов
/ 15 июля 2010

Моя первая мысль была о шаблоне фасада , который в моей книге '1003 * Head First Design Patterns ' объясняется в той же главе, что и Adapter, и сравнивается с удаленнымуправление компонентами домашнего кинотеатра.

Этот фасад будет находиться между клиентским приложением и различными брокерами.Поэтому клиенту не нужно заботиться о том, какие и сколько брокеров являются частью «театра», ему просто нужно «нажать кнопку входа в систему» ​​и «все соединения с брокерами включены».

...