2012-06-28 22 views
0

我正在使用工厂(BillFactory)来确定要实例化哪个Bill。每个Bill s(AClassBill,BClassBill等)都可以判断提供的数据是否为范围。在因子I中迭代每个账单并检查当前数据是否在当前账单范围内。如果它在范围内,我实例化该类的一个对象并返回它。工厂模式和多态使用情况

这是代码。

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种类型的Bill s(单例模式)的3个虚拟实例。这就是我解决问题的方法。我的问题是我应该使用这个虚拟实例吗?他们是否违反任何原则?

另一种方法是将in_range方法转换为静态方法。然后我不必创建实例。同样,由于这个方法是一个类特定的属性(意味着它不会在不同的实例上改变),它应该是有意义的。在这种情况下,我必须在in_range方法中硬编码这些值,或者使所有的from,torange属性都是静态的。

我应该使用什么方法?你知道更好的吗?

+1

请检查您的代码。这与你所说的不同。此外它看起来破碎。 – hakre

+0

另外我会说你可以把'Range'放到它自己的对象中 - 这可能已经解决了你的“问题”。 – hakre

+1

在那里所有的静态调用,我会说这是更多的基于类的编程比oop。 – Gordon

回答

0

尝试重温设计。看起来应该只有1个Bill类(并且创建3个不同的实例而不是3个不同的类),并且可能将calculate_bill委托给策略(策略模式)。