HORB で Observer パターン

HORB を使ったクライアント/サーバのアプリケーションで、サーバからクライ アントにイベントを通知する仕組みを実現できます。

HORBサーバとHORBクライアントによる、Observerパターンの簡単な実装例を紹介します。 このサンプルでは、サーバ側でint型の値を1秒間隔でインクリメントしています。 その値変化をクライアントで受信し、コンソールに出力しています。 動作を示す程度しか実装していません。実用にするには、最低限 Observer の削除を 追加する必要があります。

作ったクラス/インタフェースは以下の4つ。

クラス名概要
ChangeValueEvent 値の変化を通知するためのイベント
ChangeValueListener ChangeValueEvent を受信するためのリスナーインタフェース
Server 値変化を通知するサーバ
Client サーバから値の変化を受信するクライアント

これらを HORBC でコンパイルします。 クラスの依存関係があるので、コンパイルの順序を守らないとコンパイルエラー が出てコンパイルできません。 後ろの二つはどちらが先でもかまいませんが、Client が Server_Proxy に依存 しているので、Server.java を先にコンパイルする必要があります。

  1. horbc Server.java
  2. horbc ChangeValueEvent.java
  3. horbc Client.java

動作させるには、サーバ起動用とクライアント起動用の、二つのコマンドプロ ンプトが必要です。

まずサーバを起動します。 起動すると、1秒ごとに値をインクリメントしつつコンソールに表示していき ます。

サーバの起動後に、クライアントを起動します。 サーバから受信した値を、1秒ごとにコンソールに出力します。

このモデルでアプリケーションを作成した場合、 ネットワークの切断にどう対処するかが最大の問題となります。 クライアントから接続してきたコネクションを利用しているので、一旦コネクションが 切れるとクライアントにイベントを送信できなくなります。

また、WindowsXP 環境でサーバを動作させる場合は、 WindowsXP 自体の問題もあり悩ましさは倍増します。 なんと、WindowsXP のネットワークケーブルを抜くと、localhost のコネクションが 切断されてしまうのです。このは、ここで紹介したサンプルでも発生しますので、 興味がある方はお試しください。 以下、日記に書いた情報へのリンクです。

ここに書いたソースと、コンパイルしたクラスファイルを圧縮したものも 用意しました。 こちらからダウンロードできます。 ただし、HORB が必要です。 HORB はhttp://www.horbopen.org/ から入手してください。


ChangeValueEvent.java

public class ChangeValueEvent {
    int prev;
    int current;
    public ChangeValueEvent(int prev, int current){
        this.prev = prev;
        this.current = current;
    }
    public int getOldValue(){
        return prev;
    }
    public int getNewValue(){
        return current;
    }
}

ChangeValueListener.java

import horb.orb.HORBRemote;

public interface ChangeValueListener extends HORBRemote {
    public void valueChanged(ChangeValueEvent e);
}

Server.java

import horb.orb.*;
import java.util.Vector;

public class Server {
    static Vector listeners = new Vector();
    int value = 0;

    static Updater updater;

    public static void main(String argv[]) throws HORBException {
        // start a HORBServer
        HORBServer hs = new HORBServer(8887, "horbServer8887", null);

        // register an object as a HORB object
        Server server = new Server();
        HORBServer.registerObject("Server", server,"daemonServer");
    }

    public Server(){
        if (updater == null) {
            updater = new Updater();
            updater.start();
        }
    }

    public void addChangeValueListener(ChangeValueListener l){
        listeners.addElement(l);
    }

    public void removeChangeValueListener(ChangeValueListener l){
        listeners.removeElement(l);
    }

    public void setValue(int value){
        System.out.println("value=" + value);
        if(this.value != value){
            ChangeValueEvent e = new ChangeValueEvent(this.value, value);
            notifyEvent(e);
        }
        this.value = value;
    }

    private void notifyEvent(ChangeValueEvent e){
        for(int i = 0; i < listeners.size(); i++){
            ChangeValueListener l = (ChangeValueListener)listeners.elementAt(i);
            l.valueChanged(e);
        }
    }

    private class Updater extends Thread {
        private int value = 0;
        public void run(){
            while(true){
                setValue(value++);
                try{
                    Thread.sleep(1000);
                }catch (Throwable t){
                    t.printStackTrace();
                }
            }
        }
    }
}

Client.java

import horb.orb.*;

import javax.swing.*;

public class Client implements ChangeValueListener {
    static String host;
    public static void main(String argv[]) {
        host = "localhost";
        if(argv.length > 0){
            host =  argv[0];
        }
        Client client = new Client();
        client.start();
        while(true){
            try{
                Thread.sleep(100);
            }catch(Exception e){}
        }
    }

    public Client(){
    }

    public void start(){
        Server_Proxy server = new Server_Proxy("horb://" + host);
        server.addChangeValueListener(this);
    }

    public void valueChanged(ChangeValueEvent e){
        System.out.println("Received Value = " + e.getNewValue());
    }
}


HOME お勧め書籍 / Profile / リンク