2010-07-15 121 views
2

我正在創建一個客戶端擺動應用程序,該應用程序將提供/由衆多數據提供商(代理商)之一提供的數據。然而,數據提供者有不同的方式來執行相同的事情,例如,適配器模式適用於不同的接口方法具有不同參數的情況

BROKER1的登錄方法

public boolean doLogin(String username, String password); 

broker2的登錄方法

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

對於所有供應商的一組被要求的動作是一樣的 如

登錄,的getStatus,sendRequest將,的getData,註銷
(但他們有不同的參數和返回類型)

我看了一下適配器模式,但不幸的是無法使用它,因爲所需的方法有不同的參數。

適配器模式在這種情況下可用嗎?如果是的話如何?
如果不是最好的做法是什麼?

謝謝。

回答

2

模式是最佳實踐的一般準則(起點)。許多開發人員根據自己的需要「調整」模式;那麼重要的是,如果您必須使用模式,請在整個應用程序中始終使用它。

現在,回答你的問題;是的,適配器模式可以很好地用於你的情況。一個可能的解決方案(以等)可能是:

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

我的第一個想法是查看facade pattern,它在我的'Head First Design Patterns'書中,在適配器的相同章節中進行了解釋,並與家庭影院組件的遠程控制進行了比較。

此門面將坐在客戶端應用程序和各種經紀人之間。因此,客戶不必關心,「劇場」中包含哪些經紀人和多少經紀人,只需按「登錄按鈕」和「所有經紀人連接已打開」即可。

+0

我相信OP已經在他的應用中使用了某種外觀,我不確定他是否想要一次性使用所有的經紀人。他的問題更多的是不同的經紀人(可能是第三方)擁有不同的API和不同的方法論點,並且他希望統一所有這些在一個公共API中,而不管使用的是第三方。 「外觀模式」並不回答內部對象如何被操縱,而是如何將它們集成到一個簡潔的API中,這不是OP的關注點。恕我直言 – 2010-07-15 07:56:43