用 chain of responsibility 模式實作卡路里計算公式
不過卡路里計算公式只使用了「性別」和「活動量等級」二個條件,應該不需要特地使用 design pattern 才是
實務上不需要弄得這麼複雜,當作練習就好
參考
用 chain of responsibility 模式實作卡路里計算公式
不過卡路里計算公式只使用了「性別」和「活動量等級」二個條件,應該不需要特地使用 design pattern 才是
實務上不需要弄得這麼複雜,當作練習就好
參考
| <?php | |
| use App\Models\Member; | |
| abstract class AbstractCalculator | |
| { | |
| /** @var self */ | |
| private $next = null; | |
| /** | |
| * @param self $next | |
| * @return void | |
| */ | |
| public function setNext(CaloriesCalculator $next) | |
| { | |
| $this->next = $next; | |
| } | |
| /** | |
| * @param \App\Models\Member $member | |
| * @return void|\App\Models\Member | |
| */ | |
| public function next(Member $member) | |
| { | |
| if ($this->next instanceof CaloriesCalculator) { | |
| return $this->next->calculate($member); | |
| } | |
| return $member; | |
| } | |
| /** | |
| * @param \App\Models\Member $member | |
| * @return void | |
| */ | |
| abstract public function calculate(Member $member); | |
| } |
| <?php | |
| use App\Models\Member; | |
| class ActivityCalculator extends CaloriesCalculator | |
| { | |
| public function calculate(Member $member) | |
| { | |
| $ratio = 1; | |
| if ($member->activity === 1) { // 低活動量 | |
| $ratio = 1.2; | |
| } elseif ($member->activity === 2) { // 中活動量 | |
| $ratio = 1.375; | |
| } elseif ($member->activity === 3) { // 高活動量 | |
| $ratio = 1.55; | |
| } else { | |
| return $this->next($member); | |
| } | |
| $member->suggest_kcal *= $ratio; | |
| return $this->next($member); | |
| } | |
| } |
| <?php | |
| use App\Models\Member; | |
| use Illuminate\Support\Carbon; | |
| class AgeCalculator extends CaloriesCalculator | |
| { | |
| public function calculate(Member $member) | |
| { | |
| $ratio = 1; | |
| if ($member->isMale()) { | |
| $ratio = 6.8; | |
| } elseif ($member->isFemale()) { | |
| $ratio = 4.7; | |
| } else { | |
| return $this->next($member); | |
| } | |
| $age = Carbon::parse($member->birthday)->age; | |
| $member->suggest_kcal -= ($ratio * $age); | |
| return $this->next($member); | |
| } | |
| } |
| <?php | |
| use App\Models\Member; | |
| class BmrCalculator extends CaloriesCalculator | |
| { | |
| public function calculate(Member $member) | |
| { | |
| if ($member->isMale()) { | |
| $member->suggest_kcal += 66; | |
| } elseif ($member->isFemale()) { | |
| $member->suggest_kcal += 665; | |
| } else { | |
| return $this->next($member); | |
| } | |
| return $this->next($member); | |
| } | |
| } |
| <?php | |
| $step1 = new HeightCalculator(); | |
| $step2 = new WeightCalculator(); | |
| $step3 = new AgeCalculator(); | |
| $step4 = new BmrCalculator(); | |
| $step5 = new ActivityCalculator(); | |
| // 基礎代謝率 Basal metabolic rate | |
| $step1->setNext($step2); | |
| $step2->setNext($step3); | |
| $step3->setNext($step4); | |
| $memberWithBmr = $step1->calculate($member); | |
| // 每日建議攝取熱量 Recommended daily calories | |
| $step4->setNext($step5); | |
| $memberWithRdc = $step4->calculate($memberWithBmr); |
| <?php | |
| use App\Models\Member; | |
| class HeightCalculator extends AbstractCalculator | |
| { | |
| public function calculate(Member $member) | |
| { | |
| $ratio = 1; | |
| if ($member->isMale()) { | |
| $ratio = 13.7; | |
| } elseif ($member->isFemale()) { | |
| $ratio = 9.6; | |
| } else { | |
| return $this->next($member); | |
| } | |
| $member->suggest_kcal += ($ratio * $member->height); | |
| return $this->next($member); | |
| } | |
| } |
| <?php | |
| use Illuminate\Database\Eloquent\Model; | |
| class Member extends Model | |
| { | |
| public function isMale() | |
| { | |
| // ... | |
| } | |
| public function isFemale() | |
| { | |
| // ... | |
| } | |
| } |
| <?php | |
| use App\Models\Member; | |
| class WeightCalculator extends AbstractCalculator | |
| { | |
| public function calculate(Member $member) | |
| { | |
| $ratio = 1; | |
| if ($member->isMale()) { | |
| $ratio = 5; | |
| } elseif ($member->isFemale()) { | |
| $ratio = 1.8; | |
| } else { | |
| return $this->next($member); | |
| } | |
| $member->suggest_kcal += ($ratio * $member->weight); | |
| return $this->next($member); | |
| } | |
| } |