2015-10-06 10 views
2

我是C++組合模式的粉絲,我試圖在Java中設計類似的代碼。如何在Java中做一個boost樣式函數對象?

我有下面的類建立在C做回調++使用boost功能對象:

class MyEventMarshaller 
{ 
public: 
    void subscribeMessage(std::string eventKey, boost::function<void (DataType1, DataType2)> callBack) 
    { 
     m_callbackMap[eventKey].push_back(callBack); 
    } 
    void marshallLoop() 
    { 
     while(m_doStuff) 
     { 
      //Something interesting happens 
      std::string eventKey = getInterestingEventKey(); 
      if(m_callbackMap.find(eventKey) != m_callbackMap.end()) 
      { 
        BOOST_FOREACH(boost::function<void (DataType1, DataType2)> cb, m_callbackMap[eventKey]) 
        { 
         cb(getDataOne(), getDataTwo()); 
        } 
      } 
     } 
    } 
protected: 
    std::map<std::string, std::vector<boost::function<void (DataType1, DataType2)> > m_callbackMap; 
}; 

在這種情況下,想要一個事件類中註冊其處理成員函數:

m_eventHandlerPtr->subscribeMessage("SOME_EVENT_KEY", 
            boost::bind(&MyClass::MyHandler, this, _1, _2)); 

如你所見,任何類都可以註冊所有共享相同簽名的消息,並且事件編組器不需要知道哪些類可能正在註冊任何消息。人們可以將設計進一步推進,並將編組器的subscribeMessage()方法隱藏在一個函數對象中,從而使註冊類不必知道編組器的類型。

我的問題是這樣的:

將如何在Java中我最好的重複升壓功能爲對象的回調處理的目的是什麼?它甚至有可能嗎?

回答

2

的Java 8的Lambda表達式:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

所以,你可以定義任何單一方法接口:

public interface BinaryFunction { 
    String invoke(Object dataOne, Object dataTwo); 
} 

和實現事件編組在C++:

class MyEventMarshaller 
{ 
    private boolean doStuff = true; 
    private Map<String, List<BinaryFunction> > callbackMap = new HashMap<String, List<BinaryFunction>>(); 

    public void subscribeMessage(String eventKey, BinaryFunction callBack) 
    { 
     if (!callbackMap.containsKey(eventKey)) { 
      callbackMap.put(eventKey, new ArrayList<BinaryFunction>()); 
     } 

     callbackMap.get(eventKey).add(callBack); 
    } 

    public void marshallLoop() 
    { 
     while(doStuff) 
     { 
      //Something interesting happens 
      String eventKey = getInterestingEventKey(); 

      if (callbackMap.containsKey(eventKey)) 
      { 
       for (BinaryFunction cb : callbackMap.get(eventKey)) 
       { 
        System.out.println("Debug: " + cb.invoke(getDataOne(), getDataTwo())); 
       } 
      } 

      break; 
     } 
    } 

    private Object getDataTwo() { return null; } // TODO Auto-generated method stub 
    private Object getDataOne() { return null; } // TODO Auto-generated method stub 

    String getInterestingEventKey() { return "yep"; } 

} 

現在,演示程序將如下所示:

public class Program { 

    public static void main(String[] args) { 
     MyEventMarshaller instance = new MyEventMarshaller(); 

     instance.subscribeMessage("yep", (a,b) -> MessageFormat.format("{0}/{1}", a, b)); 

     instance.marshallLoop(); 
    } 
} 

Lambda表達式(a,b) -> MessageFormat.format("{0}/{1}", a, b)隱含實現BinaryFunction接口,並且是等同於做:

instance.subscribeMessage("yep", new BinaryFunction() { 
     @Override 
     public String invoke(Object a, Object b) { 
      return MessageFormat.format("{0}/{1}", a, b); 
     } 
    }); 
+0

將這項工作的非靜態成員函數,即我可以這樣做: SomeClassType someClassInstance =新SomeClassType (); (「KEY」,(a,b) - > someClassInstance.handleSomeKey(a,b)); – stix

+0

只要捕獲是最終的,是沒有問題的。 [鏈接頁面](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)完美地描述了在lambda表達式中「爲課程準備」的東西。但是您可以使用與從Java 7和Java 6的匿名嵌套類型捕獲相同的指導原則(5,也是IIRC) – sehe

1

在java中不能傳遞函數作爲一個變量,但也可以通過一個回調接口與特定的方法(doSomething的)被稱爲完全一樣調用該函數在C++中。

public interface Callback { 
    public void doSomething(); 
} 

public class MyCallback implements Callback { 
    public void doSomething() { 
     // Do something 
    } 
} 

... 

private List<Callback> callbacks; 

... 

public void addCallback(Callback callback) { 
    callbacks.add(callback); 
} 

public void do() { 
    for (Callback callback : callbacks) { 
     callback.doSomething(); 
    } 
} 
相關問題