まえに、
オブジェクト指向で開発するという場合、多態性を利用して、はじめのうちは、メディアをはっきりさせず、入力、出力を共通的なインターフェースを使って設計しておき、最終段階で実際の入出力メディアを決めるという開発方法もありえます。
と書いたけど、実際に、どうやるかを書いていなかったので、ちょっと書いてみる。
■まず、各入出力デバイスのクラスを作るんだけど・・・
Readable,Writableというインターフェースを用意する。
interface Readable { int open(String name); int read(byte[] str); int close(); String get(String key); void set(String key,String value); } interface Writable { int open(String name); int write(byte[] str); int close(); String get(String key); void set(String key,String value); } |
各入出力メディアでは、これらを継承して、入出力メディアクラスを作成する。
たとえば、データベースの場合
public class DbAccess implements Readerble,Writeable { /* * SQLマップ:openしたとき、名前とSQLの対応表 */ public HashMap sqlMap = null; // このほか、DBアクセスに必要な変数 public static initialize() { // DBの環境設定を読み込んでなければ、 // DBの環境設定を読み込む // これでSQLマップと // 接続に必要な変数は設定される } public DbAccess() { // initialize()を実行 } public int open(String name) { // nameをもとに実行するSQLを選択する // 接続に必要な変数を利用し、接続する } int write(byte[] str) { // たぶん、タブ区切りみたいな形式で来るので、 // それを分解して、openのときに選択された // SQLに埋め込み(PrepareStatementを利用してる場合、 // そのまま値を設定し) // DB書き出し実行 } int read(byte[] str) { // リードバッファにデータがない場合 // openのときに選択されたSQLを実行 // 結果をタブ区切り(セルの区切りはタブ、レコード区切りは改行) // にして、str分データセットし、のこりをリードバッファへ // リードバッファにデータがある場合 // リードバッファからstr分データセットし、 // のこりをリードバッファへ } int close(); { // 接続終了 } String get(String key) { // keyで指定された変数を返す // 指定された変数がなければなにもしない // StringでないものはtoString型等を返す } void set(String key,String value) { // keyで指定された変数を設定する // 指定された変数がなければなにもしない // 設定ファイルの形式で設定=Stringのはず } } |
のように作成する(もちろん、コメントをそのようにプログラムした上で)。
■各メディアごとの設定ファイル
上記のコメントにあるように、そーすると、DBの環境設定が必要になる。
そのDBの環境設定で、
・openのときに指定された名前に対するSQL
(writeでセットするようなところは$1とかにしておく)
・そのほか接続に必要な変数(ユーザー名、パスワード、接続URLなど)
をXMLで定義する。
このほかの入出力メディアでも、設定ファイルを用意し、そのメディア固有の情報
(ファイルの場合のファイルパスとか、メールの場合の送り先、POPサーバーなど)
は、それぞれのメディアの設定ファイルを用意する。
なお、設定ファイルは静的な情報となるので、動的に情報を変えたい場合は、setを使う。
たとえば、DBのSELECT文などで、USER_IDを動的に設定したい場合、
設定ファイルでは、名前はUSER_SELECT、
SQLは SELECT * FROM USER WHERE USER_ID=$1
とかにしておき、プログラム中で、set("$1","1235");のようにIDをセットする。
大幅に変えたいときは、set("WHERE","USER_NAME='Tom'");のように、WHERE句全体を変えられる
なんていうのもあるといいかもしれない。
ただ、あまり多用しないようにする。
■入出力ごとのjavaBeansを用意しておき・・・
そしたら、こんどは入出力ごとのJavaBeansを用意しておき、
とりあえず、まだ、メディアがきまっていなかったら、
Readerble,Writeable
でコーディングしておき、メディアがきまったら、そのメディアにする
public class zyutyu { DbAccess acc = new DbAccess(); // フィールド変数 // セッター // ゲッター public int read() { // accをオープンして、 // acc.read()して // 読み込んだ内容をセットして // acc.close()する } public int write() { // accをオープンして、 // beanの内容をレコード化し // acc.write(そのレコード)して // acc.close()する } } |
こうすると、すべてのメディアが基本的に
Openして
readして結果をタブ区切りで受け取り
beanをwriteして
クローズする
という形になっているので、たとえば、DB書き出しをメールしたりする場合でも、
DbAccessをMailAccessにかえればいいだけになる。
動的に変えたい場合は、setを利用するが、メディアを切り替えた場合、
前のメディア用のsetが残っていても、新しいメディアでそのsetのキーのものを
使っていなければ、何もしないだけなので、問題がおきにくい
(でも、そのような差異があるため、set,getは多用しないほうがいい)
■ちなみに
public static initialize()としたのは、設定ファイル読み込みを、
はじめてアクセスしたときにされてしまうと、
その「はじめてのアクセス」のときに遅れてしまうので、
システムの起動時に、
DbAccess.initialize();
のように書いて、起動時に設定ファイルを読み込ませるためです。
何でこんなことを書いたかは、もちょっとするとわかる・・・かも??