适配器模式是否可用于不同接口方法具有不同参数的情况

时间:2010-07-15 06:30:51

标签: java swing design-patterns adapter

我正在创建一个客户端摇摆应用程序,它将拥有由许多数据提供者(经纪人)之一提供的数据。然而,数据提供者有不同的方式来执行相同的事情,例如

broker1的登录方法

public boolean doLogin(String username, String password);

broker2的登录方法

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

对于所有提供者,所需的操作集是相同的 e.g

login,getstatus,sendRequest,getData,logOff
(但他们有不同的参数和返回类型)

我看了一下适配器模式但很遗憾无法使用它,因为所需的方法有不同的参数。

在这种情况下适配器模式是否可用?如果是这样的话? 如果不是最好的方法是什么?

感谢。

2 个答案:

答案 0 :(得分:3)

模式是最佳实践的一般准则(起点)。许多开发人员根据他们的需求“调整”模式;重要的是,如果您必须使用模式,请在整个应用程序中始终如一地使用它。

现在,回答你的问题;是的,适配器模式可以很好地用于您的情况。可能的解决方案(在类似中)可能是:

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...
   }
}

答案 1 :(得分:0)

我的第一个想法是调查facade pattern,在我的“Head First Design Patterns”一书中,在与适配器相同的章节中对其进行了解释,并与家庭影院组件的远程控制进行了比较。

这个门面将位于客户端应用程序和各种代理之间。所以客户不必关心,有多少经纪人是“剧院”的一部分,只需要“按下登录按钮”并“打开所有经纪人连接”。

相关问题