我正在创建一个客户端摇摆应用程序,它将拥有由许多数据提供者(经纪人)之一提供的数据。然而,数据提供者有不同的方式来执行相同的事情,例如
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
(但他们有不同的参数和返回类型)
我看了一下适配器模式但很遗憾无法使用它,因为所需的方法有不同的参数。
在这种情况下适配器模式是否可用?如果是这样的话? 如果不是最好的方法是什么?
感谢。
答案 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”一书中,在与适配器相同的章节中对其进行了解释,并与家庭影院组件的远程控制进行了比较。
这个门面将位于客户端应用程序和各种代理之间。所以客户不必关心,有多少经纪人是“剧院”的一部分,只需要“按下登录按钮”并“打开所有经纪人连接”。