0

ファクトリー ( BillFactory) を使用しBillてインスタンス化するものを決定しています。各Bills (など) はAClassBillBClassBill提供されたデータが範囲であるかどうかを判断できます。因子では、各請求書を繰り返し処理し、現在のデータが現在の請求書の範囲内にあるかどうかを確認します。範囲内にある場合は、そのクラスのオブジェクトをインスタンス化して返します。

これがコードです。

interface IBillable {
    function calculate_bill();
}

class Bill implements IBillable {

    protected $from;
    protected $to;
    protected $rate;
    protected $unit_amount;

    public function get_from() {
        return $this->from;
    }

    public function get_to() {
        return $this->to;
    }

    public function get_rate() {
        return $this->rate;
    }

    public function in_range($unit_amount) {
        $_from = $this->get_from();
        $_to = $this->get_to();
        return ($_from <= $unit_amount && $_to >= $unit_amount);
    }

    public function calculate_bill() {
        return ($this->get_rate() * $this->unit_amount);
    }

}

class AClassBill extends Bill {

    protected $from = 0;
    protected $to = 100;
    protected $rate = 3.05;

    public function __construct($amount) {
        $this->unit_amount = $amount;
    }

}

class BClassBill extends Bill {

    protected $from = 101;
    protected $to = 400;
    protected $rate = 4.29;

    public function __construct($amount) {
        $this->unit_amount = $amount;
    }

    public function calculate_bill() {
        if ($this->unit_amount >= 301) {
            return $this->get_rate() * $this->unit_amount;
        } else {
            $bill1 = $this->get_rate() * ($this->unit_amount - $this->get_from() + 1);
            $bill2 = new AClassBill($this->get_from() - 1);
            return $bill1 + $bill2->calculate_bill();
        }
    }

}

class CClassBill extends Bill {

    protected $from = 401;
    protected $to = -1; // not used
    protected $rate = 7.89;

    public function __construct($amount) {
        $this->unit_amount = $amount;
    }

    public function in_range($unit_amount) {
        $_from = $this->get_from();
        return ($_from <= $unit_amount);
    }

}

class BillFactory {

    private static $s1 = null;
    private static $s2 = null;
    private static $s3 = null;

    public static function instance($units) {
        if (is_null(self::$s1))
            self::$s1 = new AClassBill(0);
        if (is_null(self::$s2))
            self::$s2 = new BClassBill(0);
        if (is_null(self::$s3))
            self::$s3 = new CClassBill(0);

        if (self::$s1->in_range($units)) {
            $b = new AClassBill($units);
        } else if (self::$s2->in_range($units)) {
            $b = new BClassBill($units);
        } else if (self::$s3->in_range($units)) {
            $b = new CClassBill($units);
        } else {
            $b = false;
        }
        return $b;
    }

}

for ($i = 1; $i <= 500; $i++) {
    $b = BillFactory::instance($i);
    if ($b !== false) {
        printf("%10s\t%04d\t%04.2f\t%04d\t%06.2f\n", get_class($b), $i, $b->get_rate(), $i, $b->calculate_bill());
    }
}

問題はファクトリ クラス ( BillFactory) にあります。Bill3 種類のs (シングルトン パターン) の3 つのダミー インスタンスを作成したことに気付くでしょう。これが私の問題を解決した方法です。私の質問は、このダミー インスタンスを使用する必要があるかどうかです。の原則に違反していますか?

もう 1 つの方法は、in_rangeメソッドを静的メソッドに変換することです。次に、インスタンスを作成する必要はありません。また、このin_rangeメソッドはクラス固有のプロパティであるため (異なるインスタンスでは変更されないことを意味します)、意味があるはずです。その場合、これらの値をメソッドにハードコーディングするin_rangeか、すべてのfrom,toおよびrangeプロパティを静的にする必要があります。

どのようなアプローチを使用する必要がありますか? もっといいの知ってる?

4

1 に答える 1

0

デザインを見直してみてください。Bill クラスは 1 つだけ (3 つの異なるクラスではなく 3 つの異なるインスタンスを作成) し、calculate_bill を戦略 (戦略パターン) に委譲する必要があるようです。

于 2012-06-29T07:07:27.620 に答える