atwiki-logo
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このウィキの更新情報RSS
    • このウィキ新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡(不具合、障害など)
ページ検索 メニュー
とりあえず雑記帳(跡地)
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
とりあえず雑記帳(跡地)
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
とりあえず雑記帳(跡地)
ページ検索 メニュー
  • 新規作成
  • 編集する
  • 登録/ログイン
  • 管理メニュー
管理メニュー
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • このウィキの全ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ一覧(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このwikiの更新情報RSS
    • このwikiの新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡する(不具合、障害など)
  • atwiki
  • とりあえず雑記帳(跡地)
  • とりあえずインターフェース入門
  • そしてフレームワークへ

とりあえず雑記帳(跡地)

そしてフレームワークへ

最終更新:2011年11月15日 23:14

fujiyan

- view
管理者のみ編集可

1箇所たりとも修正したくない


先のBinaryOperationは、少ないとはいえ、やはり修正している事実に変わりはありません。
「修正せずに拡張する」の精神にのっとり、さらに工夫をしてみましょう。

演算の追加を、BinaryOperation自身で行わずに、外部から演算オブジェクトを
追加するように変更することで、BinaryOperationの本質的な部分は一切変更せずに拡張できるようにします。

package jp.fujiyan.binaryoperation5;
 
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 二項演算フレームワークです。
 * 
 * @author fujiyan
 */
public class BinaryOperationFramework {
	// 入力値の最小
	private static final int MIN_VALUE = -99999;
	// 入力値の最大
	private static final int MAX_VALUE = 99999;
 
	// 選択肢
	private static final int FINISH = 0;
 
	// 演算子のリスト
	private List<IBinaryOperator> operatorList = new ArrayList<IBinaryOperator>();
 
	/**
	 * ユーザ入力を返します。
	 * 
	 * @param prompt プロンプト文
	 * @return ユーザ入力文字列
	 */
	private static String input(String prompt) throws IOException {
		System.out.println(prompt);
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String str = in.readLine();
		if (str == null) {
			// Ctrl+Zによる中断
			throw new EOFException("中断されました。");
		}
		return str;
	}
 
	/**
	 * 整数値を問い合わせます。
	 * 
	 * @return 整数値
	 */
	private static int askValue(int seq) throws IOException {
		int value = 0;
		boolean invalid = true;
		while (invalid) {
			// 整数値が入力されるまで
			String ret = input(String.valueOf(seq) + "番目の数値を入力してください(" + MIN_VALUE + "~" + MAX_VALUE + "の整数)。");
			try {
				value = Integer.parseInt(ret);
			} catch (NumberFormatException e) {
				// 整数値として有効でない文字列
				System.out.println("入力された値は整数値ではありません。");
				continue;
			}
 
			invalid = (value < MIN_VALUE) || (value > MAX_VALUE);
			if (invalid) {
				// 無効な入力
				System.out.println("入力された数値が範囲を超えています。");
			}
		}
 
		return value;
	}
 
	/**
	 * 演算子を追加します。
	 * 
	 * @param operator 演算子
	 */
	public void addOperator(IBinaryOperator operator) {
		operatorList.add(operator);
	}
 
	/**
	 * 操作を問い合わせます。
	 * 
	 * @return 操作の選択肢
	 */
	private int askOperation() throws IOException {
		StringBuilder sb = new StringBuilder();
		int i = 0;
		sb.append(i).append(":").append("終了");
		while (i < operatorList.size()) {
			sb.append(" ");
			sb.append(i + 1).append(":").append(operatorList.get(i).getChoiseString());
			i++;
		}
		String prompt = "操作を番号で選択してください。(" + new String(sb) + ")";
 
		int operation = 0;
		boolean invalid = true;
		while (invalid) {
			// 有効な選択肢が入力されるまで
			String ret = input(prompt);
 
			try {
				operation = Integer.parseInt(ret);
				invalid = (operation < 0) || (operation > operatorList.size());
			} catch (NumberFormatException e) {
				// 数値として有効でない文字列
			}
 
			if (invalid) {
				// 無効な入力
				System.out.println("正しい番号を選択してください。");
			}
		}
 
		return operation;
	}
 
	/**
	 * 演算を行います。
	 * 
	 * @param operation 操作の選択肢
	 * @param value1 値1
	 * @param value2 値2
	 */
	private void execute(int operation, int value1, int value2) {
		IBinaryOperator op = operatorList.get(operation - 1);
		op.calculate(value1, value2);
 
		if (op.isError()) {
			// エラーあり
			System.out.println(op.getErrorMessage());
			return;
		}
 
		System.out.println(op.getExpression() + " の答えは " + op.getResult() + " です。");
	}
 
	/**
	 * 計算を実施します。
	 */
	public void perform() {
		try {
			int operation = askOperation();
			while (operation != FINISH) {
				// "終了"が選択されるまで
				int val1 = askValue(1);
				int val2 = askValue(2);
 
				execute(operation, val1, val2);
 
				operation = askOperation();
			}
			System.out.println("終了します。");
		} catch (EOFException e) {
			// Ctrl+Zによる中断
			System.err.println(e.getMessage());
		} catch (Exception e) {
			// その他例外
			System.err.println("なんかまずいことが発生しました。");
			e.printStackTrace();
		}
	}
}
 

メインが演算を追加する
/*
 * オブジェクト指向版
 * フレームワーク化
 */
package jp.fujiyan.binaryoperation5;
 
import jp.fujiyan.binaryoperation5.operator.Addition;
import jp.fujiyan.binaryoperation5.operator.Division;
import jp.fujiyan.binaryoperation5.operator.Multiplication;
import jp.fujiyan.binaryoperation5.operator.Power;
import jp.fujiyan.binaryoperation5.operator.Subtraction;
 
public class Main {
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        BinaryOperationFramework framework = new BinaryOperationFramework();
 
        framework.addOperator(new Addition());
        framework.addOperator(new Subtraction());
        framework.addOperator(new Multiplication());
        framework.addOperator(new Division());
        framework.addOperator(new Power());//$$$$$修正$$$$$
 
        framework.perform();
    }
}
 

※他のクラスは変更なし

ココまで来ると、いよいよ「二項演算フレームワーク」として、演算の追加には、計算処理を扱うクラス(BinaryOperationFramework)は一切変更しなくてすむようになりました。

フレームワークには、3つの要素が出現します。
  • フレームワーク(BinaryOperationFramework、IBinaryOperator、StandardOperator)
全体の処理を流れを定義します(BinaryOperationFramework)。拡張部分をインターフェースとして提供します(IBinaryOperator)。場合によっては、実装を補助する基底クラスも提供します(StandardOperator)。

  • プラグイン(Addition、Subtraction、Multiplication、Division、Power)
フレームワークから提供されたインターフェースを実装したクラスです。フレームワークに処理させたい内容を実装します。

  • コントローラ(Main)
フレームワークとプラグインを結びつけます。
StrutsやSpring等のフレームワークでは、コントローラの処理を外部ファイルで記述させたり、命名規則で制御することで、プログラムの再コンパイルを不要にしています。


…と、えらく大雑把で駆け足でしたが、インターフェースの使い道がお伝えできたでしょうか。

「インターフェースを活用する=フレームワークを作る」と言ってもいいでしょう。
ぜひぜひ、いろんなフレームワークを作ってみてください。

(了)
「そしてフレームワークへ」をウィキ内検索
LINE
シェア
Tweet
とりあえず雑記帳(跡地)
記事メニュー

メニュー

  • トップページ
  • コメント
  • とりあえずインターフェース入門
  • Yesod
  • Haskell
  • Slim3
  • JavaScript
  • Google App Engine
  • Android
  • Facebook
  • GWT
  • OpenSocial
  • Struts 2
  • Subversion
  • Apache
  • JSONIC
  • Flex

  • WebコミックLibraryについて

公式サイト

  • Yesod
  • Haskell
  • Slim3
  • JavaScript - MDN
  • App Engine for Java
  • Android Developers
  • Google Web Toolkit
  • Struts
  • OpenSocial
  • OSDE

  • ToDo

ここを編集
記事メニュー2
間違いの御指摘は
コメントまでm(_ _)m

更新履歴

取得中です。


ここを編集

総数: -
本日: -
昨日: -
人気記事ランキング
  1. Struts 2
もっと見る
最近更新されたページ
  • 4407日前

    Haskell
  • 4407日前

    Yesod
  • 4407日前

    トップページ
  • 4517日前

    メニュー
  • 4518日前

    Struts 2
  • 4544日前

    コメント
  • 4713日前

    Google App Engine
  • 4750日前

    Slim3/環境構築とプロジェクト作成
  • 4775日前

    Google App Engine/キャッシュの計画
  • 4785日前

    Slim3/文字列の部分一致検索とページング
もっと見る
人気記事ランキング
  1. Struts 2
もっと見る
最近更新されたページ
  • 4407日前

    Haskell
  • 4407日前

    Yesod
  • 4407日前

    トップページ
  • 4517日前

    メニュー
  • 4518日前

    Struts 2
  • 4544日前

    コメント
  • 4713日前

    Google App Engine
  • 4750日前

    Slim3/環境構築とプロジェクト作成
  • 4775日前

    Google App Engine/キャッシュの計画
  • 4785日前

    Slim3/文字列の部分一致検索とページング
もっと見る
ウィキ募集バナー
新規Wikiランキング

最近作成されたWikiのアクセスランキングです。見るだけでなく加筆してみよう!

  1. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  2. MadTown GTA (Beta) まとめウィキ
  3. R.E.P.O. 日本語解説Wiki
  4. シュガードール情報まとめウィキ
  5. ソードランページ @ 非公式wiki
  6. AviUtl2のWiki
  7. Dark War Survival攻略
  8. シミュグラ2Wiki(Simulation Of Grand2)GTARP
  9. ありふれた職業で世界最強 リベリオンソウル @ ウィキ
  10. 星飼いの詩@ ウィキ
もっと見る
人気Wikiランキング

atwikiでよく見られているWikiのランキングです。新しい情報を発見してみよう!

  1. アニヲタWiki(仮)
  2. ストグラ まとめ @ウィキ
  3. ゲームカタログ@Wiki ~名作からクソゲーまで~
  4. 鹿乃つの氏 周辺注意喚起@ウィキ
  5. 初音ミク Wiki
  6. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  7. 発車メロディーwiki
  8. 機動戦士ガンダム バトルオペレーション2攻略Wiki 3rd Season
  9. 検索してはいけない言葉 @ ウィキ
  10. Grand Theft Auto V(グランドセフトオート5)GTA5 & GTAオンライン 情報・攻略wiki
もっと見る
全体ページランキング

最近アクセスの多かったページランキングです。話題のページを見に行こう!

  1. チンポ画像収集場 - 検索してはいけない言葉 @ ウィキ
  2. 参加者一覧 - ストグラ まとめ @ウィキ
  3. ドンキーコング バナンザ - アニヲタWiki(仮)
  4. 機体一覧 - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  5. 危険度7 - 検索してはいけない言葉 @ ウィキ
  6. キングクルール - アニヲタWiki(仮)
  7. ひの らん/エピソード6 - ストグラ まとめ @ウィキ
  8. 魔獣トゲイラ - バトルロイヤルR+α ファンフィクション(二次創作など)総合wiki
  9. 生きたメキシコ - 検索してはいけない言葉 @ ウィキ
  10. コメント/雑談・質問 - マージマンション@wiki
もっと見る

  • このWikiのTOPへ
  • 全ページ一覧
  • アットウィキTOP
  • 利用規約
  • プライバシーポリシー

2019 AtWiki, Inc.