2012-10-26 70 views
1

我受到Signals events pattern in AS3的啓發,它取代了閃存的本地事件。而且在性能和可讀性方面都表現更好。Java - 信號事件模式

所以我想在Java中實現它。

這種模式的主要思想是,你正在使用對象而不是類型,通過這個時間來找到「Dispatcher」類來處理你的事件分派(調度事件正在向所有的監聽者發送事件)

因此讓我們跳到代碼: 在這個例子中,我將創建AlarmManager並處理他的報警事件。

首先,我們需要建立我們的接口爲這個事件

public interface IAlarmEvent { 
    void alarmEventHandler(String alert); 
} 

現在事件本身:

public class AlarmEvent extends Signal<IAlarmEvent> implements IAlarmEvent { 

    public void alarmEventHandler(String alert) { 
     dispatch("alarmEventHandler", alert); 
    } 
} 

這裏是AlarmManger:

public class AlarmManager { 

    public final AlarmEvent alarmEvent = new AlarmEvent(); 

    public void init(){ 
     // Dispatching the event 
     alarmEvent.alarmEventHandler("Wake up"); 
    } 

} 

這裏是一個活動誰在聽這個事件:

public class MainActivity extends Activity implements IAlarmEvent{ 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     AlarmManager alarmManager = new AlarmManager(); 
     alarmManager.alarmEvent.addListener(this); 

     alarmManager.init(); 
    } 

    public void alarmEventHandler(String alert) { 
     Log.d("MyLog", "Event : " + alert); 
    } 
} 

這裏是我如何寫作信號類

public abstract class Signal<T> { 
    private LinkedHashMap<T, T> listeners = new LinkedHashMap<T, T>(); 

    protected void dispatch(String methodName, Object...arguments){ 
     Set<T> keySet = listeners.keySet(); 
     if(keySet.size() == 0){ 
      return; 
     } 

     Iterator<T> iterator = keySet.iterator(); 

     Method method = null; 
     do{ 
      T listener = iterator.next(); 
      if(method == null){ 
       try { 
        Class<?>[] classes = new Class<?>[arguments.length]; 
        for(int i = 0; i < arguments.length; i++){ 
         classes[i] = arguments[i].getClass(); 
        } 
        method = listener.getClass().getMethod(methodName, classes); 
       } catch (NoSuchMethodException e) { 
        e.printStackTrace(); 
       } 
      } 

      try { 
       method.invoke(listener, arguments); 
      } catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } catch (InvocationTargetException e) { 
       e.printStackTrace(); 
      } 

     }while(iterator.hasNext()); 
    } 

    public void addListener(T listener) { 
     listeners.put(listener, listener); 
    } 

    public void removeListener(T listener) { 
     listeners.remove(listener); 
    } 
} 

這種模式是:

  • 快 - 無需搜索類型,並觸發此事件,它立即進行。
  • 具有很好的可讀性 - 僅僅通過查看課程,您就可以確切瞭解他發送的事件以及每個事件的外觀。

然而,它不工作。如果我爲我的接口使用原語,則Signal無法找到該方法並調用它。我不喜歡將方法名稱傳遞給信號的想法。任何想法如何改善這一點?你對這種模式有什麼看法?

+0

只是一個供參考已經執行:'設置的keySet = listeners.keySet(); (keySet == null || keySet.size()== 0){ return; } keySet永遠不會爲空 – bgs

+0

@BGS ok我修正了它 –

+0

我在哪裏可以找到你的代碼以便使用它(請獲得一些github回購?)?我也喜歡as3信號。謝謝。 – SudoPlz

回答

0

好像這個圖案在這些類

java.util.Observable 
java.util.Observer 
+0

然而,這非常有趣,這正是我不想做的。 Observable只知道觀察者,通過所有觀察者實現的通用接口。所以在更新方法中,我將不得不創建一個switch case來找出事件類型。這就是信號模式正在解決的問題。我吸收你閱讀我基於的文章中的更多內容。 –