生産者・ブローカ・消費者のシミュレーション(パート2)
戻る
$ ./UnitTest.sh Broker
現在の在庫数=0 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 95.00
現在の在庫数=1 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 90.00
現在の在庫数=2 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 85.00
現在の在庫数=3 : 許容サイズ=10
Meat を生産しました! -- 製造コスト= 10.00
現在の資金残高= 75.00
現在の在庫数=4 : 許容サイズ=10
Meat を生産しました! -- 製造コスト= 10.00
現在の資金残高= 65.00
現在の在庫数=5 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 60.00
現在の在庫数=6 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 55.00
現在の在庫数=7 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 50.00
現在の在庫数=8 : 許容サイズ=10
GardenStuff を生産しました! -- 製造コスト= 5.00
現在の資金残高= 45.00
現在の在庫数=9 : 許容サイズ=10
Meat を生産しました! -- 製造コスト= 10.00
現在の資金残高= 35.00
-------------------------------------------------------------
末松さんの資金残高= 35.00 山口さんの資金残高= 0.00
末松さんの資金残高= 40.50 山口さんの資金残高=194.50
末松さんの資金残高= 46.00 山口さんの資金残高=189.00
末松さんの資金残高= 51.50 山口さんの資金残高=183.50
末松さんの資金残高= 62.50 山口さんの資金残高=172.50
末松さんの資金残高= 73.50 山口さんの資金残高=161.50
末松さんの資金残高= 79.00 山口さんの資金残高=156.00
末松さんの資金残高= 84.50 山口さんの資金残高=150.50
末松さんの資金残高= 90.00 山口さんの資金残高=145.00
末松さんの資金残高= 95.50 山口さんの資金残高=139.50
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
/******/ 末松さんさんの生産在庫が空ですので取引できません。
末松さんの資金残高=106.50 山口さんの資金残高=128.50
::::::::::::::
Actor.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
abstract public class Actor {
/** 資金 */
protected double fund;
/** 名前 */
protected String name;
/** 在庫 */
protected Stock stock;
public Actor( String name ) {
this.name = name;
}
protected String getName() {
return name;
}
/** 資金の初期値を設定する */
protected void setFund( double fund ) {
this.fund = fund;
}
protected double getFund() {
return fund;
}
/** 資金を使う */
protected void spendMoney( double cost ) {
fund -= cost;
}
/** 在庫を取得する */
protected Stock getStock() {
return this.stock;
}
}
::::::::::::::
Broker.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
public class Broker extends Actor implements Drawable {
/** 在庫数の許容最大値(とりあえず固定値) */
private final int STOCK_SIZE = 10;
public Broker( String name ) {
super( name );
stock = new Stock( STOCK_SIZE );
}
/** 生産者より生産物を仕入れる */
public void stockup( Product product ) {
stock.store( product );
// 資金を使う
super.spendMoney( ProductPriceManager.getSellingPriceToBroker( product ) );
}
/** 購入するための資金に余裕があるか */
public boolean canAffordToBuy( double price ) {
return ( fund >= price );
}
public static void main( String[] args ) throws Throwable {
Producer producer = new Producer( "末松さん" );
producer.setFund( 100.0 );
for ( int i = 0;i < 10;i++ ) {
producer.produce();
System.out.printf( "現在の資金残高=%6.2f\n", producer.getFund() );
try {
Thread.sleep( 50 );
} catch ( Throwable t ) {
throw t;
}
}
System.out.println( "-------------------------------------------------------------" );
Broker broker = new Broker( "山口さん" );
System.out.printf( "%sの資金残高=%6.2f\t", producer.getName(), producer.getFund() );
System.out.printf( "%sの資金残高=%6.2f\n", broker.getName(), broker.getFund() );
broker.setFund( 200.0 );
for ( int i = 0;i < 20;i++ ) {
producer.sellProduct( broker );
System.out.printf( "%sの資金残高=%6.2f\t", producer.getName(), producer.getFund() );
System.out.printf( "%sの資金残高=%6.2f\n", broker.getName(), broker.getFund() );
}
}
}
::::::::::::::
Drawable.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
public interface Drawable {}
::::::::::::::
DrawingPanel.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import BasicPackage.*;
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class DrawingPanel extends AbstractDrawingPanel {
public DrawingPanel() {
super();
start( 100 );
}
public void setActors() {}
public void drawActors( Graphics g ) {}
public void paintComponent( Graphics g ) {
clearScreen( g );
}
}
::::::::::::::
FactoryAutomation.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import BasicPackage.*;
/**
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class FactoryAutomation extends AbstractJApplet {
public FactoryAutomation() {
setPanel( new DrawingPanel(), 800, 600 );
init();
}
}
::::::::::::::
GardenStuff.java
::::::::::::::
/**
* <pre>野菜</pre>
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class GardenStuff extends Product {
private final double cost = 5.0;
public GardenStuff( Producer producer ) {
super( producer );
}
/** 現在の製造コストを返す */
public double getCost() {
return cost * ProductingCostManager.getCurrentRate();
}
}
::::::::::::::
Meat.java
::::::::::::::
/**
* <pre>食肉</pre>
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*
*/
public class Meat extends Product {
private final double cost = 10.0;
public Meat( Producer producer ) {
super( producer );
}
/** 現在の製造コストを返す */
public double getCost() {
return cost * ProductingCostManager.getCurrentRate();
}
static public void main( String[] args ) {
Meat meat = new Meat( new Producer( "山田さん" ) );
System.out.printf( "%5.2f\n", meat.getCost() );
}
}
::::::::::::::
Producer.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
public class Producer extends Actor implements Drawable {
/** 在庫数の許容最大値(とりあえず固定値) */
private final int STOCK_SIZE = 10;
public Producer( String name ) {
super( name );
stock = new Stock( STOCK_SIZE );
}
public synchronized void produce() {
if ( !stock.isAcceptable() ) {
System.out.println( "これ以上在庫を増やすことは出来ません。" );
return ;
}
// 市場の動向に従い生産物を決める
Product product = ( Product ) TrendInformationProvider.notifyHotSellingProduct( this );
if ( ! canAffordToProduce( product.getCost() ) ) {
System.out.println( "もう資金に余裕がありません!" );
return ;
}
System.out.printf( "%30s を生産しました! -- 製造コスト=%6.2f\n",
product.getClass().getName(), product.getCost() ) ;
// 生産物を在庫に格納
stock.store( product );
// 資金を使う
super.spendMoney( product.getCost() );
}
/** 生産するための資金に余裕があるか */
private boolean canAffordToProduce( double cost ) {
return ( fund >= cost );
}
/**
* 生産物をブローカに販売する
* 販売する生産物は、キューの先頭に入っているものとする
* 取引自体はTransactionManagerに処理を委譲する
*/
public void sellProduct( Broker broker ) throws Throwable {
try {
TransactionManager.transact( this, broker );
} catch ( Throwable t ) {
throw t;
}
}
/** 単体テスト */
static public void main( String[] args ) throws Throwable {
Producer producer = new Producer( "大山さん" );
producer.setFund( 100.0 );
for ( int i = 0;i < 15;i++ ) {
producer.produce();
System.out.printf( "現在の資金残高=%6.2f\n", producer.getFund() );
try {
Thread.sleep( 500 );
} catch ( Throwable t ) {
throw t;
}
}
System.out.println( "-------------------------------------------------------------------" );
Producer producer2 = new Producer( "藤田さん" );
producer2.setFund( 40.0 );
for ( int i = 0;i < 15;i++ ) {
producer2.produce();
System.out.printf( "現在の資金残高=%6.2f\n", producer2.getFund() );
try {
Thread.sleep( 500 );
} catch ( Throwable t ) {
throw t;
}
}
}
}
::::::::::::::
Product.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
abstract public class Product {
protected Producer producer;
public Product( Producer producer ) {
this.producer = producer;
}
/**
* 季節によりコストが変更するものとする
*/
abstract double getCost();
}
::::::::::::::
ProductPriceManager.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class ProductPriceManager {
static double getSellingPriceToBroker( Product product ) {
return 1.1 * product.getCost();
}
static double getSellingPriceToConsumer( Product product ) {
return 1.3 * product.getCost();
}
}
::::::::::::::
ProductingCostManager.java
::::::::::::::
/**
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
* 製造コストの季節変動の割合を返す
*/
public class ProductingCostManager {
static public double getCurrentRate( ) {
// ロジックはあとで変更する
if ( System.currentTimeMillis() % 5 == 0 ) {
return 1.25;
} else {
return 1.00;
}
}
}
::::::::::::::
Stock.java
::::::::::::::
import java.util.*;
import java.util.concurrent.*;
/**
* <pre>在庫エンティティ</pre>
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class Stock implements Storable {
private int size;
private ArrayBlockingQueue queue;
public Stock( int size ) {
this.size = size;
queue = new ArrayBlockingQueue( size );
}
/** キューにデータを格納する */
public void store( Object obj ) {
boolean status = queue.offer( obj );
}
/** キューの先頭データを参照する(削除はしない)*/
public Object peek() {
return queue.peek();
}
/** キューからデータを取り出す */
public Object pickup() throws Throwable {
Object object;
try {
object = queue.take();
} catch ( Throwable t ) {
throw t;
}
return object;
}
/** 追加可能かどうか */
public boolean isAcceptable() {
System.out.println( "現在の在庫数=" + queue.size() + " : 許容サイズ=" + size );
return ( queue.size() != size );
}
/** キューが空かどうか */
public boolean isEmpty() {
return ( queue.size() == 0 );
}
}
::::::::::::::
Storable.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
public interface Storable {
/** 格納する */
public void store( Object obj );
/** 取り出す */
public Object pickup() throws Throwable;
/** 先頭要素を参照する */
public Object peek();
/** 追加可能かどうか */
public boolean isAcceptable();
}
::::::::::::::
TransactionManager.java
::::::::::::::
/**
* <pre>
* 抽象クラスActorを継承したクラス(Prpducer, Broker, Consumer)同士のトランザクションを代行するクラス
* お互いに他のオブジェクトを直接CALLしないようにしてクラス間の依存性を極力少なくする(→疎結合)
* </pre>
* $Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class TransactionManager {
static public void transact( Producer producer, Broker broker ) throws Throwable {
Stock stock = producer.getStock();
if ( stock.isEmpty() ) {
System.out.println( "/******/ " + producer.getName() + "さんの生産在庫が空ですので取引できません。" );
return ;
}
Product product;
try {
// 在庫内の先頭要素を参照する
product = ( Product ) stock.peek();
} catch ( Throwable t ) {
throw t;
}
// ブローカへの売値を決める
double price = ProductPriceManager.getSellingPriceToBroker( product );
// ブローカに購入資金がない場合は、取引しないまま終了
if ( !broker.canAffordToBuy( price ) ) {
System.out.println( broker.getName() + "さんに購入資金がありません!" );
return ;
}
try {
// キューから生産物を取り出す
product = ( Product ) stock.pickup();
// ブローカが入荷する
broker.stockup( product );
// 入金する
double currentFund = producer.getFund();
producer.setFund( currentFund + price );
} catch ( Throwable t ) {
throw t;
}
}
}
::::::::::::::
TrendInformationProvider.java
::::::::::::::
/**
$Id: FA2.html,v 1.1 2009/06/22 16:11:43 kishi Exp kishi $
*/
public class TrendInformationProvider {
static public Product notifyHotSellingProduct( Producer producer ) {
// ロジックはあとで変更する
if ( System.currentTimeMillis() % 3 == 0 ) {
return new Meat( producer );
} else {
return new GardenStuff( producer );
}
}
}
戻る