Problem
我有個透過JNA去存取硬體資料的程式:
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); } }
某天有了需要做存取控管需求,因此我在Bus Library介面上增加了兩個methods:
boolean lockBus(byte bus); boolean releaseBus(byte bus);
而sendData中,在實際請求前會先lockBus,使用後再releaseBus:
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); } } }
問題是: 如果我有10個bus相關操作,不就要寫很多一樣的code嗎?
How to resolve?
一開始我就想,除了aop、intercepter等方式外,function pointer應該就能解決我的問題: 只要有一個method會在critical action前後做lock與release就可以了。類似以下:
void busAction(Function* criticalAction){ lockAndWait(); criticalAction->invoke(); release(); }
最後宣告一個名為BusAction的FunctionalInterface:
@FunctionalInterface public interface BusAction { boolean invoke(); }
而我處理lock與release的method如下:
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); } } }
最後就是sendData與getData:
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); }); }
透過以上方法,可以讓我大幅減少duplicated code。
後記
如果不想額外增加Interface,也可以直接使用Runable或Callable,取決於你是否要讓語義更清楚而已。
留言
張貼留言