PHP设计模式之策略模式

1、恐龙函数

我们看一个很简单的电子商务网站的功能:

1、普通会员,商品不打折。

2、高级会员,商品打9折。

3、vip会员,商品打8折。

我们可能会这样设计代码:

例:

  1. <?php 
  2. //打折类 
  3. class discountor 
  4. public function getDiscount($rank
  5. switch ($rank) { 
  6. case 'common'
  7. $discount = 1; 
  8. break
  9. case 'advance'
  10. $discount = 0.9; 
  11. break
  12. case 'vip'
  13. $discount = 0.8; 
  14. break
  15. return $discount
  16. $discountor = new discountor(); 
  17. echo $discountor->getDiscount('advance'); 
  18. ?> 

现在由于每个等级的折扣,不需要计算,所以看起来还是很简单的。

如果$discount不是那么简单出来的,需要分析,比如最近我们给vip的折扣是否有促销,或者这款产品本身是否有特别优惠。

那么这个代码将非常长,这个getDiscount函数的代码也会超长。

等写好这个类的代码,你会发现似乎这不是一个类,而是一个巨大的函数。

我们定义了一个恐龙般巨大的函数,如果一旦不同等级的计算方法发生变动,这个getDiscount函数的修改将是一场噩梦。

2、恐龙类

前面我们搞了一个巨型函数,我们先设法优化这个函数的代码,至少便于修改这个函数。

其实我们分析这个函数,由于switch,其实分三个情况来计算折扣,那么我们想到将三个情况的计算,分到不同的函数。

例:

  1. <?php 
  2. //打折类 
  3. class discountor 
  4. public function getDiscount($rank
  5. switch ($rank) { 
  6. case 'common'
  7. $discount = $this->getCommonDiscount(); 
  8. break
  9. case 'advance'
  10. $discount = $this->getAdvanceDiscount(); 
  11. break
  12. case 'vip'
  13. $discount = $this->getVipDiscount(); 
  14. break
  15. return $discount
  16.  
  17. protected function getCommonDiscount() 
  18. $discount = 1; 
  19. return $discount
  20.  
  21. protected function getAdvanceDiscount() 
  22. $discount = 0.9; 
  23. return $discount
  24.  
  25. protected function getVipDiscount() 
  26. $discount = 0.8; 
  27. return $discount
  28. $discountor = new discountor(); 
  29. echo $discountor->getDiscount('advance'); 
  30. ?> 

这样一来,我们只要修改相关的函数,就可以完成某种级别用户的折扣计算。

不过还是有个问题,这个类太大了,几个和级别相关的函数里面承担了太大的业务处理。

我们消灭了一个恐龙般的函数,但是这个类还是恐龙类。

3、锦囊妙计

前面我们分拆函数getDiscount的时候,已经有了思路,就是拆开一些代码来简化。

在三国演义中,赵云身上带着的锦囊,在不同情况下拆开来解决问题,其实就是封装的思路。

我们不必把discountor当作锦囊,而是把他当作赵云,做几个锦囊类来给赵云用。

例:

  1. <?php 
  2. //打折接口 
  3. interface IDiscountor 
  4. public function getDiscount(); 
  5. //普通用户打折类 
  6. class commonDiscountor implements IDiscountor 
  7. public function getDiscount() 
  8. $discount = 1; 
  9. return $discount
  10. //高级用户打折类 
  11. class advanceDiscountor implements IDiscountor 
  12. public function getDiscount() 
  13. $discount = 0.9; 
  14. return $discount
  15. //vip用户打折类 
  16. class vipDiscountor implements IDiscountor 
  17. public function getDiscount() 
  18. $discount = 0.8; 
  19. return $discount
  20. //打折类 
  21. class discountor 
  22. public function getDiscount($rank
  23. switch ($rank) { 
  24. case 'common'
  25. $discountor = new commonDiscountor(); 
  26. break
  27. case 'advance'
  28. $discountor = new advanceDiscountor(); 
  29. break
  30. case 'vip'
  31. $discountor = new vipDiscountor(); 
  32. break
  33. return $discountor->getDiscount(); 
  34.  
  35. $discountor = new discountor(); 
  36. echo $discountor->getDiscount('advance'); 
  37. ?> 

这个就是策略模式(Strategy),将不同情况的算法分拆到不同的类(比如advanceDiscountor类),然后调用者(discountor类)根据具体的情况,用算法类的对象来处理。

思考:

策略模式是一种常用的模式,我们可以用它来封装不同情况下的算法代码,方便修改。

但是策略模式,如果乱用,那么就会出来很多多余的算法类,也就是分拆过度。

另外,策略类一般直接用new来新建对象调用算法,他与类名是用比较高的关联度,所以有时候,需要考虑用工厂或其他方法来进一步优化。

转载请注明:代码家园 » PHP设计模式之策略模式

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)