JAvaインタフェースを用いてC/C++関数ポインタ機能(インタフェースコールバック)を実現

3573 ワード

1つのプロジェクトでは、1つのデバイスクラスが存在する場合、ネットワークポート、シリアルポート、CAN、IIC、SPIなど、複数の通信インタフェースを備えている.このデバイスは、様々な通信インタフェースの開閉および読み書き方法を提供する必要がある.インタフェースに通信に必要なメソッド定義が含まれていることを宣言できます.次に、異なる通信インタフェースのインスタンス化方法を定義します.これにより、デバイスクラスインスタンスオブジェクトは、実際に使用される通信インタフェースのタイプに応じて、対応するインスタンス化インタフェースを使用することを選択することができる.
メソッドステップ
インタフェースの宣言
public interface Drive {
    int open();
    int close();
    int read();
    int write();
}

クラスの使用を宣言
public class Device {
    public Drive drive;//        。
    Device(Drive drive){
        this.drive = drive;
    }
    Device(){}
    public int open(){
        drive.open();//      
        return 0;
    }
    public int close(){
        drive.close();
        return 0;
    }
    public int read(){
        drive.read();
        return 0;
    }
    public int write(){
        drive.write();
        return 0;
    }
}

インタフェースのインスタンス化
 Drive drive_1 = new Drive() {
            @Override
            public int open() {
                Log.i(TAG, "open: drive_1");
                return 0;
            }

            @Override
            public int close() {
                Log.i(TAG, "close: drive_1");
                return 0;
            }

            @Override
            public int read() {
                Log.i(TAG, "read: drive_1");
                return 0;
            }

            @Override
            public int write() {
                Log.i(TAG, "write: drive_1");
                return 0;
            }
        };
        Drive drive_2 = new Drive() {
            @Override
            public int open() {
                Log.i(TAG, "open: drive_2");
                return 0;
            }

            @Override
            public int close() {
                Log.i(TAG, "close: drive_2");
                return 0;
            }

            @Override
            public int read() {
                Log.i(TAG, "read: drive_2");
                return 0;
            }

            @Override
            public int write() {
                Log.i(TAG, "write: drive_2");
                return 0;
            }
        };

インスタンス・オブジェクトを作成し、インタフェース・メンバーに値を割り当てます.
        @Override
        public void run() {
            Log.i(TAG, "run:     ");
            Device device = new Device();
            Log.i(TAG, "run:        ");
            device.drive = drive_1;
            device.open();
            device.write();
            device.read();
            device.close();
            device.drive = drive_2;
            Log.i(TAG, "run:        ");
            device.open();
            device.write();
            device.read();
            device.close();
            Log.i(TAG, "run:     ");
        }

ドライブを1 deviceに値を割り当てる.drive時に呼び出されたのはdrive_1のインスタンスメソッド.
09-20 06:47:12.982 9033-9050/? I/TimerThread: open: drive_1
09-20 06:47:12.982 9033-9050/? I/TimerThread: write: drive_1
09-20 06:47:12.982 9033-9050/? I/TimerThread: read: drive_1
09-20 06:47:12.982 9033-9050/? I/TimerThread: close: drive_1

ドライブを2 deviceに値を割り当てる.drive時に呼び出されたのはdrive_2の例を示します.
09-20 06:47:12.982 9033-9050/? I/TimerThread: open: drive_2
09-20 06:47:12.982 9033-9050/? I/TimerThread: write: drive_2
09-20 06:47:12.982 9033-9050/? I/TimerThread: read: drive_2
09-20 06:47:12.982 9033-9050/? I/TimerThread: close: drive_2

インタフェースコールバックは、プログラムの結合度を低減し、プログラムを容易に拡張することができる.