Skip to content

Instantly share code, notes, and snippets.

@gundamew
Last active January 19, 2021 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gundamew/454c6cfa74b454dfa0bc6371f6bf246e to your computer and use it in GitHub Desktop.
Save gundamew/454c6cfa74b454dfa0bc6371f6bf246e to your computer and use it in GitHub Desktop.
A chain of responsibility pattern practice.
<?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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment