如果您在团队中并且程序员为您提供了创建,读取,更新和删除方法的界面,那么如何避免类型切换?
引用清洁代码敏捷软件工艺手册:
public Money calculatePay(Employee e)
throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
Run Code Online (Sandbox Code Playgroud)
这个功能有几个问题.首先,它很大,当添加新的员工类型时,它会增长.其次,它显然不止一件事.第三,它违反了单一责任原则7(SRP),因为改变的原因不止一个.第四,它违反了开放封闭原则8(OCP),因为每当添加新类型时它必须改变.但是这个函数最糟糕的问题可能是有无限数量的其他函数具有相同的结构.例如,我们可以
isPayday(Employee e, Date date),
Run Code Online (Sandbox Code Playgroud)
要么
deliverPay(Employee e, Money pay),
Run Code Online (Sandbox Code Playgroud)
或许多其他人.所有这些都具有相同的有害结构.
这本书告诉我使用工厂模式,但这让我觉得我不应该真正使用它.
再次引用这本书:
这个问题的解决方案(参见清单3-5)是将switch语句埋在一个抽象工厂9的地下室,永远不会让任何人看到它.
switch语句难看吗?
实际上,员工对象应该有自己的计算工资函数,可以为您提供工资.这个计算工资函数会根据员工的类型而变化.
这样,由对象来定义实现,而不是对象的用户.
abstract class Employee
{
public abstract function calculatePay();
}
class HourlyEmployee extends Employee
{
public function calculatePay()
{
return $this->hour * $this->pay_rate;
}
}
class SalariedEmployee extends Employee
{
public function calculatePay()
{
return $this->monthly_pay_rate;
}
}
Run Code Online (Sandbox Code Playgroud)
在构建工厂时,然后在那里执行switch语句,并且只执行一次,以构建员工.
让我们说员工是一个阵列,而员工的类型是在 $array['Type']
public function buildEmployee($array)
{
switch($array['Type']){
case 'Hourly':
return new HourlyEmployee($array);
break;
case 'Salaried':
return new SalariedEmployee($array);
break;
}
Run Code Online (Sandbox Code Playgroud)
最后,计算工资
$employee->calculatePay();
Run Code Online (Sandbox Code Playgroud)
现在,根据员工的类型,不需要多个switch语句来计算员工的工资.它只是员工对象的一部分.
免责声明,我是未成年人,所以我对这些付款的计算方式并不完全正面.但论证的基础仍然有效.应该在对象中计算工资.
免责声明2,这是PHP代码.但是再一次,这个论点应该适用于任何语言.