目的
「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。
今回は「State/Strategyによるタイプコードの置き換え」について書きます。
「State/Strategyによるタイプコードの置き換え」 について
クラスの振る舞いに影響するタイプコードがあるが、サブクラス化はできない。
タイプコードがそのオブジェクトの生存期間中に変化するか、サブクラス化が不都合な理由が別にあるときに適用できます。
例
変更前
<?php
class Employee
{
private $_type;
private $_monthlySalary;
private $_commission;
private $_bonus;
const ENGINEER = 0;
const SALESMAN = 1;
const MANAGER = 2;
public function __construct($type)
{
$this->_type = $type;
}
public function payAmount()
{
$this->_monthlySalary = 2000;
$this->_commision = 1000;
$this->_bonus = 3000;
switch ($this->_type) {
case self::ENGINEER:
return $this->_monthlySalary;
case self::SALESMAN:
return $this->_monthlySalary + $this->_commission;
case self::MANAGER:
return $this->_monthlySalary + $this->_bonus;
default:
throw new Exception('不正な従業員');
}
}
}
$e1 = new Employee(2);
echo $e1->payAmount() . "\n";
変更後
<?php
abstract class EmployeeType
{
const ENGINEER = 0;
const SALESMAN = 1;
const MANAGER = 2;
abstract function getTypeCode();
public static function newType($code)
{
switch ($code) {
case self::ENGINEER:
return new Engineer();
case self::SALESMAN:
return new Salesman();
case self::MANAGER:
return new Manager();
default:
throw new Exception('不正な従業員コード');
}
}
}
class Engineer extends EmployeeType
{
public function getTypeCode()
{
return self::ENGINEER;
}
}
class Salesman extends EmployeeType
{
public function getTypeCode()
{
return self::SALESMAN;
}
}
class Manager extends EmployeeType
{
public function getTypeCode()
{
return self::MANAGER;
}
}
class Employee2
{
private $_type;
private $_monthlySalary;
private $_commission;
private $_bonus;
public function __construct($type)
{
$this->setType($type);
}
public function getType()
{
return $this->_type->getTypeCode();
}
public function setType($type)
{
$this->_type = EmployeeType::newType($type);
}
public function payAmount()
{
$this->_monthlySalary = 2000;
$this->_commision = 1000;
$this->_bonus = 3000;
switch ($this->getType()) {
case EmployeeType::ENGINEER:
return $this->_monthlySalary;
case EmployeeType::SALESMAN:
return $this->_monthlySalary + $this->_commission;
case EmployeeType::MANAGER:
return $this->_monthlySalary + $this->_bonus;
default:
throw new Exception('不正な従業員');
}
}
}
$e2 = new Employee2(2);
echo $e2->payAmount() . "\n";