生産者・ブローカ・消費者のシミュレーション(パート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 );

        }

    }
}


戻る inserted by FC2 system