差異處
這裏顯示兩個版本的差異處。
java:java8:functionalinterface:method_reference [2017/02/24 14:31] tony [How to resolve?] |
java:java8:functionalinterface:method_reference [2023/06/25 09:48] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | {{tag>java lambda}} | ||
- | ====== Method Reference ====== | ||
- | ===== Problem ===== | ||
- | 我有個透過JNA去存取硬體資料的程式: | ||
- | <code java> | ||
- | public interface Bus extends Library { | ||
- | Bus INSTANCE = (Bus) Native.loadLibrary( "buslib", Bus.class); | ||
- | |||
- | boolean sendData(byte bus, byte data[]); | ||
- | boolean getData(byte bus, byte data[]); | ||
- | } | ||
- | |||
- | public boolean sendData(byte bus, byte data[]){ | ||
- | synchronized (Bus.class) { | ||
- | return Bus.INSTANCE.sendData(bus, data); | ||
- | } | ||
- | } | ||
- | public boolean getData(byte bus, byte data[]){ | ||
- | synchronized (Bus.class) { | ||
- | return Bus.INSTANCE.getData(bus, data); | ||
- | } | ||
- | } | ||
- | </code> | ||
- | 某天有了需要做存取控管需求,因此我在Bus Library介面上增加了兩個methods: | ||
- | <code java> | ||
- | boolean lockBus(byte bus); | ||
- | boolean releaseBus(byte bus); | ||
- | </code> | ||
- | 而sendData中,在實際請求前會先lockBus,使用後再releaseBus: | ||
- | <code java> | ||
- | public boolean sendData(byte bus, byte data[]){ | ||
- | synchronized (Bus.class) { | ||
- | try { | ||
- | boolean ret = false; | ||
- | if (!(ret = Bus.INSTANCE.lockBus(bus))) { | ||
- | return ret; | ||
- | } | ||
- | return Bus.INSTANCE.sendData(bus, data); | ||
- | } finally { | ||
- | Bus.INSTANCE.releaseBus(bus); | ||
- | } | ||
- | } | ||
- | } | ||
- | </code> | ||
- | 問題是: 如果我有10個bus相關操作,不就要寫很多一樣的code嗎? | ||
- | ===== How to resolve? ===== | ||
- | 一開始我就想,除了aop、intercepter等方式外,function pointer應該就能解決我的問題: 只要有一個method會在critical action前後做lock與release就可以了。最後使用了Java8的FunctionalInterface,宣告以下介面: | ||
- | <code java> | ||
- | @FunctionalInterface | ||
- | private interface BusAction { | ||
- | boolean invoke(); | ||
- | } | ||
- | </code> | ||
- | 而我處理lock與release的method如下: | ||
- | <code java> | ||
- | private boolean invokeBusAction(byte bus, BusAction action){ | ||
- | synchronized (Bus.class) { | ||
- | try { | ||
- | boolean ret = false; | ||
- | if (!(ret = Bus.INSTANCE.lockBus(bus))) { | ||
- | return ret; | ||
- | } | ||
- | return action.invoke(); | ||
- | } finally { | ||
- | Bus.INSTANCE.releaseBus(bus); | ||
- | } | ||
- | } | ||
- | } | ||
- | </code> | ||
- | 最後就是sendData與getData: | ||
- | <code java> | ||
- | public boolean sendData(byte bus, byte data[]){ | ||
- | return invokeBusAction(bus, ()->{ | ||
- | return Bus.INSTANCE.sendData(bus, data); | ||
- | }); | ||
- | } | ||
- | |||
- | public boolean getData(byte bus, byte data[]){ | ||
- | return invokeBusAction(bus, ()->{ | ||
- | return Bus.INSTANCE.getData(bus, data); | ||
- | }); | ||
- | } | ||
- | </code> | ||
- | 透過以上方法,可以讓我大幅減少duplicated code。 | ||
- | ===== Reference ===== | ||
- | * [[https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html|Oracle Java - Method Reference]] | ||
- | * [[http://stackoverflow.com/questions/34888904/function-pointers-as-parameters-in-java-8|function-pointers-as-parameters-in-java-8]] | ||
- | |||
- | |||
- | ===== ===== | ||
- | ---- | ||
- | \\ | ||
- | ~~DISQUS~~ |