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

发布于 2024-09-09 19:15:48 字数 519 浏览 5 评论 0原文

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

broker1的登录方法

public boolean doLogin(String username, String password);

brok​​er2的登录方法

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

对于所有提供者,所需的操作集是相同的 例如

登录、getstatus、sendRequest、getData、logOff
(但它们有不同的参数和返回类型)

我查看了适配器模式,但不幸的是我无法很好地使用它,因为所需的方法有不同的参数。

在这种情况下可以使用适配器模式吗?如果是这样怎么办?
如果不是,最好的方法是什么?

谢谢。

I am creating a client side swing app that will have data provided by/from one of many data providers(brokers). The data providers however, have varying ways of perfoming same things e.g.

broker1's login method

public boolean doLogin(String username, String password);

broker2's login method

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

For all providers the set of required actions is the same
e.g

login, getstatus, sendRequest, getData, logOff
(but they have different params and return types)

I took a look at the adapter pattern but am unfortunately not able to use it well as the required methods have different parameters.

Is the adapter pattern usable in this case? if so how?
If not what would be the best way of doing this?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

り繁华旳梦境 2024-09-16 19:15:48

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

现在,回答你的问题;是的,适配器模式非常适合您的情况。一个可能的解决方案(类似)可能是:

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

等等。

Patterns are general guidelines (starting point) of best practices. Many developers "adapts" the patterns to their needs; the important thing is, then, if you must use a pattern, use it consistently throughout your whole application.

Now, to answer your question; yes the adapter pattern can very well be used in your situation. A possible solution (in the like) could be:

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

Then

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

Or

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

Of course this is a very general approach. If you know that one method will be receiving strings for all parameters, you could also have a abstract signature like :

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

Then your concrete implementation would be :

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

etc.

晨与橙与城 2024-09-16 19:15:48

我的第一个想法是研究 外观模式,在我的 'Head First Design Patterns'一书,与适配器在同一章中进行了解释,并与远程控制进行了比较用于家庭影院组件。

这个外观将位于客户端应用程序和各个代理之间。因此,客户端不必关心哪些经纪人以及有多少经纪人属于“剧院”,只需“按下登录按钮”和“所有经纪人连接都已打开”。

My first thought was looking into the facade pattern, which, in my 'Head First Design Patterns' book, is explained in the same chapter as Adapter and compared with a remoted control for home theatre components.

This facade would sit between the client app and the various brokers. So the client wouldn't have to care, which and how many brokers are part of the 'theatre', it just have to 'press the login button' and 'all broker connections are switched on'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文