2012-06-28 4 views
0

Я использую фабрику (BillFactory), чтобы определить, какой Bill для создания экземпляра. Каждый из Bill s (AClassBill, BClassBill и т. Д.) Может определить, находится ли диапазон данных. В множителе I перебираем по каждому из счетов и проверяем, находятся ли текущие данные в текущем диапазоне Bills. Если его в диапазоне я создаю объект этого класса и верну его.Использование фабрики и полиморфизма

Вот код.

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). Вы заметите, что я создал 3 фиктивных экземпляра из 3 типов Bill s (singleton pattern). Вот как я решил свою проблему. Мой вопрос в том, следует ли использовать эти фиктивные экземпляры? Нарушают ли они какой-либо принцип ?

Другой способ заключается в том, чтобы преобразовать метод in_range в статический. Тогда мне не нужно создавать экземпляр. Кроме того, поскольку этот метод in_range является свойством класса (означает, что он не изменяется в разных экземплярах), он должен иметь смысл. В этом случае я должен либо жестко закодировать эти значения в методе in_range, либо сделать все свойства from, to и range статическими.

Какой подход следует использовать? Вы знаете лучшего?

+1

Просмотрите ваш код. Это отличается от того, о чем вы говорите. Также он выглядит сломанным. – hakre

+0

Также я бы сказал, что вы можете поместить «Range» в свой собственный объект, который, вероятно, уже решает ваш «Проблема». – hakre

+1

со всеми статическими вызовами, я бы сказал, что это более классное программирование, чем oop. – Gordon

ответ

0

Попробуйте пересмотреть дизайн. Похоже, что должен быть только 1 класс Билла (и создавать 3 разных экземпляра не 3 разных класса) и, возможно, делегировать calculate_bill в Стратегии (шаблон стратегии).

Смежные вопросы