第11回 アプリケーションの構成

第11回 アプリケーションの構成
~CUI自動販売機の完成!~
学習目標

簡単なオブジェクト指向アプリケーションが
書ける



関連の実装ができる
オブジェクトの構造を構成できる
シーケンス図が読める
11.1 プログラムの仕様を決める

11.1.1 自動販売機が提供するサービス
自動販売機アプリケーション

CUI(Character User Interface)による、自
動販売機アプリケーションの構築
>商品を選択してください
[1]コーラ
[2]ソーダ
[3]お茶
>お金を入れてください
100
どのようなアプリケーションを作るの?
プログラムの仕様を決めよう
11.1.1
自動販売機が提供するサービス

あなたが考える、自動販売機が行う主な
サービスを考えてみよう
自動販売機が提供するサービス

管理者に対するサービス



商品種類の管理
商品の在庫管理
ユーザ(購入する人)に対するサービス

商品の購入
目的の階層構造

自動販売機を管理する(管理者)

商品種類を管理する




商品種類を追加する
商品種類を削除する
取扱っている商品種類を確認する
在庫を管理する


商品を補充する
在庫を確認する
商品を購入する

ユーザへのサービスを考える

商品を購入する




金を投入する
商品を選択する
商品を受け取る
おつりを受け取る
今度は少し詳しく目的を書いてみよう
商品を購入する(詳細)

商品を購入する

金を投入する


商品を選択する


Idを指定する
商品を受け取る





投入金勘定に金を追加する


(細かくなりすぎないよう
分かりにくくならない程度
まで書けばよい)
商品種類を検索する
商品保管庫を取得する
商品保管庫から商品を取り出す
商品を表示する
おつりを受け取る

階層が深くなるにつれ、
目的が手段に近くなる
おつりを計算する
おつりを表示する
投入金勘定をリセットする
1.2 オブジェクトの構造を考える



11.2.1 これまで作ったプログラム
11.2.2 オブジェクトの構造をつなげるには
11.2.3 オブジェクトの構造を構築するため
の実装
11.2.1 これまで
作ったプログラム

自動販売機を管理する(管理者)

商品種類を管理する




商品種類を追加する
商品種類を削除する
取扱っている商品種類を確認する
在庫を管理する


商品を補充する
在庫を確認する
つい
なま
げま
れで
ば作
でっ
きた
るプ
はロ
グ
ずラ
ム
を
①商品種類管理プログラム
商品種類
- 商品番号
- 商品名
- 価格
クラス図
インスタンス図
商品種類リスト
0..n
+ 追加()
1 + 削除()
種類A:商品種類
商品番号=1001
商品名=コーラ
価格=120
種類B:商品種類
商品番号=1002
商品名=ソーダ
価格=120
リストA
:商品種類リスト
種類C:商品種類
商品番号=1004
商品名=DDレモン
価格=120
②商品管理プログラム
クラス図
商品保管庫
商品
- 製造年月日
0..n
インスタンス図
+ 追加()
1 + 削除()
商品A:商品
製造年月日=2002/1/21
商品B:商品
製造年月日=2002/1/22
商品C:商品
製造年月日=2002/1/23
保管庫A
:商品保管庫
11.2.2 オブジェクト
の構造をつなげるには

①商品と商品種類の関係
クラス図
商品保管庫
商品
- 製造年月日
0..n
インスタンス図
+ 追加()
1 + 削除()
商品A:商品
製造年月日=2002/1/21
商品B:商品
日付だけでは
どのような種類か
わからない
製造年月日=2002/1/22
商品C:商品
製造年月日=2002/1/23
保管庫A
:商品保管庫
解決案Ⅰ

商品に名前と価格を加える
クラス図
商品
- 商品名
- 価格
- 製造年月日
商品保管庫
+ 追加()
+ 削除()
商品A:商品
インスタンス図
商品名=コーラ
価格=120
製造年月日=2002/1/21
商品B:商品
商品名=コーラ
価格=120
製造年月日=2002/1/22
商品C:商品
商品名=ソーダ
価格=120
製造年月日=2002/1/23
保管庫A
:商品保管庫
解決案Ⅱ

商品と商品種類をリンクする
商品種類
- 商品番号
- 商品名
- 価格
商品保管庫
商品
- 製造年月日
0..n
種類A:商品種類
商品A:商品
商品番号=1001
商品名=コーラ
価格=120
製造年月日=2002/1/21
種類B:商品種類
製造年月日=2002/1/22
商品番号=1002
商品名=ソーダ
価格=120
商品C:商品
商品B:商品
製造年月日=2002/1/23
+ 追加()
1 + 削除()
保管庫A
:商品保管庫
どちらがよい解決法か?

どちらでもうまくいく。


問題はどちらがよいプログラムになるか
利点・欠点を挙げてみよう
ポイントⅠ

価格の変更はどちらがしやすいか

商品に名前を加えた場合


商品からある名前の商品をすべて検索して、すべ
て書き換える必要がある
商品種類とリンクする場合

商品種類一ヶ所ですむ
ポイントⅡ

ユーザが商品を買う時を考える


「商品」を選ぶのか、「商品種類」で選ぶのか
取り扱っている商品を知る必要があるか

その種類の商品がなくなってしまった場合、売り切
れなのか、それとも取り扱っていないのか区別する
必要があるか
自動販売機の場合、
「商品」も「商品種類」も別の意味を持っている
→意味ごとにまとめてカタマリに
②商品種類と
商品保管庫の関係

問題点

異なる商品がおなじ保管庫に入っている
コーラA:商品
製造年月日=2002/1/21
コーラB:商品
製造年月日=2002/1/22
ソーダA:商品
製造年月日=2002/1/23
保管庫A
:商品保管庫
解決案

種類ごとに保管庫を用意する
種類A:商品種類
コーラA:商品
製造年月日=2002/1/21
コーラ保管庫
:商品保管庫
商品番号=1001
商品名=コーラ
価格=120
コーラB:商品
製造年月日=2002/1/22
ソーダA:商品
製造年月日=2002/1/23
種類B:商品種類
ソーダ保管庫
:商品保管庫
商品番号=1002
商品名=ソーダ
価格=120
2つのプログラムの結合

下図のようなインスタンス構造ができる

クラス図を書いてみよう
コーラA:商品
製造年月日=2002/1/21
種類A:商品種類
コーラ保管庫
:商品保管庫
コーラB:商品
商品番号=1001
商品名=コーラ
価格=120
製造年月日=2002/1/22
種類B:商品種類
ソーダA:商品
製造年月日=2002/1/23
ソーダ保管庫
:商品保管庫
商品番号=1002
商品名=ソーダ
価格=120
リストA
:商品種類リスト
解答例
商品
- 製造年月日
0..n
0..n
1
商品保管庫
+ 補充()
+ 取り出し()
+ 表示()
1
1
商品種類
- 商品番号
- 商品名
1 - 価格
商品種類リスト
0..n
+
+
1+
+
追加()
削除()
検索()
表示()
11.2.3 オブジェクト
の構造を構築するための実装



①商品と商品種類
②商品保管庫と商品種類
③既に実装されている部分
商品
- 製造年月日
関連
0..n
0..n
1
商品保管庫
+ 補充()
+ 取り出し()
+ 表示()
1
1
商品種類
- 商品番号
- 商品名
1 - 価格
商品種類リスト
0..n
+
+
1+
+
追加()
削除()
検索()
表示()
①商品と商品種類
クラス図
インスタンス図
商品種類
- 商品番号
- 商品名
- 価格
商品
- 製造年月日
種類A:商品種類
商品A:商品
商品番号=1001
商品名=コーラ
価格=120
製造年月日=2002/1/21
種類B:商品種類
製造年月日=2002/1/22
商品番号=1002
商品名=ソーダ
価格=120
商品C:商品
商品B:商品
製造年月日=2002/1/23
①商品と商品種類
//商品クラス(抜粋)
public class Item {
例題11-1
(Item.java)
private String date;//製造年月日
private ItemType itemType;//商品に対応する商品種類
//コンストラクタ
public Item(String newDate,ItemType newItemType) {
date = newDate;
itemType = newItemType;
}
//商品に対応する商品種類を取得する
public ItemType getItemType() {
return itemType;
}
}
参照を追加
コンストラクタで
参照を設定
取得メソッドを追加
②商品保管庫と商品種類
商品保管庫
クラス図
インスタンス図
+ 補充()
+ 取り出し()
+ 表示()
1
商品種類
- 商品番号
- 商品名
1 - 価格
種類A:商品種類
コーラ保管庫
:商品保管庫
商品番号=1001
商品名=コーラ
価格=120
種類B:商品種類
ソーダ保管庫
:商品保管庫
商品番号=1002
商品名=ソーダ
価格=120
②商品保管庫と商品種類
例題11-1
(ItemType.java)
//商品種類クラス(抜粋)
public class ItemType {
private
private
private
private
int id;
String name;
int price;
ItemStock itemStock;
//商品ID
//商品名
//価格
//この種類の商品だけを格納する商品保管庫
//コンストラクタ
public ItemType(String newName,int newPrice,int newID) {
name = newName;
price = newPrice;
id = newID;
itemStock = new ItemStock();
}
//商品保管庫を取得する
public ItemStock getItemStock(){
return itemStock;
}
}
コンストラクタで
保管庫を生成
③既につながっている部分

商品と商品保管庫の関連

前回キューで実装されている
クラス図
インスタンス図
商品保管庫
商品
- 製造年月日
0..n
+ 追加()
1 + 削除()
商品A:商品
製造年月日=2002/1/21
商品B:商品
製造年月日=2002/1/22
商品C:商品
製造年月日=2002/1/23
保管庫A
:商品保管庫
③既につながっている部分

その他

商品種類と商品種類リスト


配列や連結リストを使って実装した
金と勘定

前回にスタックを利用して実装した
④関連の実装 まとめ

1対1の実装


参照で実装
コンストラクタで設定、または生成



取得メソッドを実装
1対多の実装

配列や、連結リストを使って実装



設定メソッドを用意しても良い
方法はその他いろいろある
追加、削除メソッドを実装
発展

双方向の参照を持つにはどうすればよいか
11.3 オブジェクト
の構造を構築、操作する

11.3.1 オブジェクトの構造を構築、操作す
るプログラム




①商品種類を生成して、リストに追加する
②商品を生成して、補充する
③金を投入し、商品を購入する
11.3.2 シーケンス図


①記法
②シーケンス図例
11.3.1 オブジェクトの
構造を構築・操作するプログラム

①商品種類を生成して、リストに追加する
例題11-1
(Example11_1.java)
「A」
/**
* 商品種類の管理、商品の管理、商品の販売を行うプログラム
*/
public class Example11_1 {
//メイン
public static void main(String[] args) {
ItemTypeList itemTypeList = new ItemTypeList();
Account account = new Account();
//--------管理者-------//商品種類を追加
itemTypeList.add(new ItemType("cola",120,1001));
itemTypeList.add(new ItemType("soda",120,1002));
ソーダ保管庫
:商品保管庫
コーラ保管庫
:商品保管庫
種類A:商品種類
種類B:商品種類
商品番号=1001
商品名=コーラ
価格=120
商品番号=1002
商品名=ソーダ
価格=120
//商品種類リストを生成
//投入金勘定を生成
//コーラを追加
//ソーダを追加
リストA
:商品種類リスト
②商品を生成して、補充する
商品B:商品
商品A:商品
製造年月日=2002/1/22
製造年月日=2002/1/21
例題11-1
(Example11_1.java)
「B」
//コーラ在庫を追加
//コーラの保管庫を取得
ItemStock colaStock;//コーラの保管庫
ItemType colaItemType;//コーラ商品種類
colaItemType = itemTypeList.search(1001); //コーラ商品種類を検索
colaStock = colaItemType.getItemStock();//コーラ保管庫を取得
ソーダ保管庫
:商品保管庫
コーラ保管庫
:商品保管庫
種類A:商品種類
種類B:商品種類
商品番号=1001
商品名=コーラ
価格=120
商品番号=1002
商品名=ソーダ
価格=120
//コーラを補充
colaStock.supply(new Item("2002/04/28",colaItemType));
colaStock.supply(new Item("2002/04/29",colaItemType));
リストA
:商品種類リスト
③金を投入し、商品を購入する
//商品を購入する
//金を投入する
account.insert(new Money(100));
account.insert(new Money(50));
//100円投入
//50円投入
//商品を選択する
int id = 1001;//コーラ
//商品を受け取る
//商品を取り出す
colaItemType = itemTypeList.search(id);//商品種類を検索
colaStock = colaItemType.getItemStock();//保管庫を取得
Item item = colaStock.takeout();
//商品を一つ取り出す
System.out.println("製造年月日が"+item.getDate()+"の
"+item.getItemType().getName()+"を購入しました");
//おつりを受け取る
int amount;//投入総額
amount = account.getAmount();
int change;//おつり
change = amount - item.getItemType().getPrice();
account.reset();//投入金勘定を空にする
System.out.println("おつりは"+change+"円です");
}
例題11-1
(Example11_1.java)
「C」
<練習問題>
インスタンスの構造
を書いてみよう
解答例1
//商品を購入する
//金を投入する
account.insert(new Money(100));
account.insert(new Money(50));
//100円投入
//50円投入
例題11-1
(Example11_1.java)
「C」
商品B:商品
製造年月日=2002/1/22
//商品を選択する
int id = 1001;//コーラ
//商品を受け取る
//商品を取り出す
colaItemType = itemTypeList.search(id);//商品種類を検索
colaStock = colaItemType.getItemStock();//保管庫を取得
Item item = colaStock.takeout();
//商品を一つ取り出す
System.out.println("製造年月日が"+item.getDate()+"の
"+item.getItemType().getName()+"を購入しました");
//おつりを受け取る
int amount;//投入総額
amount = account.getAmount();
int change;//おつり
change = amount - item.getItemType().getPrice();
account.reset();//投入金勘定を空にする
System.out.println("おつりは"+change+"円です");
}
ソーダ保管庫
:商品保管庫
コーラ保管庫
:商品保管庫
種類A:商品種類
種類B:商品種類
商品番号=1001
商品名=コーラ
価格=120
商品番号=1002
商品名=ソーダ
価格=120
リストA
:商品種類リスト
解答例2 勘定の変遷
100円投入された時点
50円投入された時点
金A:金
金A:金
金B:金
値=100
値=100
値=50
投入金勘定
:勘定
投入金勘定
:勘定
購入後
投入金勘定
:勘定
12.3.2 シーケンス図

構造が変化する過程を図式化する
ソーダ保管庫
:商品保管庫
コーラ保管庫
:商品保管庫
種類A:商品種類
種類B:商品種類
商品番号=1001
商品名=コーラ
価格=120
商品番号=1002
商品名=ソーダ
価格=120
ex)このような構造が
どのように構築されたか
シーケンス図
リストA
:商品種類リスト
①記法
インスタンス
(インスタンス名:クラス名)
商品種類を追加する
Example11_1
: 商品種類リ
スト
コーラ : 商品
種類
コーラ保管庫 :
商品保管庫
ソーダ : 商品
種類
ソーダ保管庫 :
商品保管庫
生成
時
間
軸
生成
追加(コーラ)
メッセージのやり取り
生成
(メソッドのコール)
追加(ソーダ)
生成
②シーケンス図例
(1)商品種類を生成して、リストに追加する
商品を補充する
Example11_1
: 商品種類リ
スト
コーラ : 商品
種類
コーラ保管庫 :
商品保管庫
検索(1001)
保管庫取得()
生成(コーラ)
追加(商品4/28)
生成(コーラ)
追加(商品4/29)
商品4/28 : 商
品
商品4/29 : 商
品
(2)商品種類を生成して、リストに追加する
商品を補充する
Example11_1
: 商品種類リ
スト
コーラ : 商品
種類
コーラ保管庫 :
商品保管庫
検索(1001)
保管庫取得()
生成(コーラ)
追加(商品4/28)
生成(コーラ)
追加(商品4/29)
商品4/28 : 商
品
商品4/29 : 商
品
(3)金を投入し、商品を購入する

記述してみましょう
(3)金を投入し、商品を購入する 解答例
:
Example11_1
100円 : 金
50円 : 金
: 勘定
: 商品種類リ
スト
生成
追加(100円)
生成
追加(50円)
検索(1001)
保管庫取得()
商品取り出し()
製造年月日取得()
総額取得()
リセット()
コーラ : 商品
種類
コーラ保管庫 :
商品保管庫
コーラA : 商
品
シーケンス図で明らかになること

シーケンス図を書く利点を議論してみよう
シーケンス図の利点

時間の流れに沿ってオブジェクトの構造の変化
の過程を追える



クラス図、オブジェクト図では明らかでない動的な変
化を追える
オブジェクトのメッセージのやり取り(メソッドの呼
び出し)を追える
そのオブジェクトにどのような役割があるかが分
かりやすくなる

そのオブジェクトがどのようなメッセージを受けている
のか
1.4 CUIアプリケーションの構築




①メニューの構成
②プログラムの構成
③クラス図
④ソース
1.4 CUIアプリケーションの構築

メニューを表示してユーザに入力を促す対
話型アプリケーション
例題11-2
//メインメニュー(CUIVMApp.java(11_2)から抜粋)
public void mainMenu(){
(CUIVMApp.java)
//無限ループ
while(true){
//ユーザが自動販売機を利用する目的を選ぶ
System.out.println("メインメニュー:(1,自動販売機の管理をする 2,自動販売機を利用する q,自動販売機の終了)");
String input = Input.getInput();
//選ばれた目的を実行する
if (input.equals("1")){
adminApp.adminMenu();
}else if(input.equals("2")){
userApp.userMenu();
}else if(input.equals("q")){
System.exit(0);
}
}
//自動販売機の管理をする
//自動販売機を利用する
//自動販売機の終了
①メニューの構成
管理者メニュー
メインメニュー
ユーザメニュー
②プログラムの構成
adminMenu()
main()
mainMenu()
addItemType()
addItem()
…
CUIAdminApp
Example11_2
CUIVMApp
userMenu()
insertCoin()
selectItemType()
…
CUIUserApp
起動役を分離する

起動役と、本体を分離することによって、よ
り分かりやすいプログラムになります
main()
Example11_2
起動役
mainMenu()
CUIVMApp
本体
③クラス図

自動販売機機のアプリケーションプログラム
は、勘定と商品種類リストだけ知っている

関連をたどることによって、すべてのオブジェクトに
たどり着け、構造を変化させることが可能
勘定
金
- 価値
CUIUserApp
+ 追加()
+ 削除()
商品種類
- 名前
- 商品番号
0..n
- 価格
商品種類リスト
+ 追加()
1 + 削除()
商品保管庫
商品
- 製造年月日
0..n
+ 追加()
1 + 削除()
CUIAdminApp
④ソース




Example11_2.java
CUIVMApp.java
CUIAdminApp.java
CUIUserApp.java

UserAppは、メソッドが実装されていません。
練習問題で各自実装するようになっています