Czytam Czysty Kod Roberta C. Martina i nie rozumiem jednej części dotyczącej korzystania z polimorfizmu zamiast instrukcji switch
.
Mając klasę Payroll.java
public Money calculatePay(Employee e)
throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateComissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
W treści odnajdujemy taki fragment:
Z tą funkcją wiąże się wiele problemów. Po pierwsze jest duża, a po dodaniu kolejnego typu pracownika urośnie jeszcze bardziej. Po drugie jasne jest, że wykonuje jeszcze jedną operację. Po trzecie narusza zasadę pojedynczej odpowiedzialności (SRP), ponieważ istnieje więcej niż jeden powód uzasadniający zmianę. Po czwarte, narusza zasadę otwarty-zamknięty (OCP), ponieważ musi się zmieniać przy każdym dodaniu nowego typu. ...
Autor proponuje takie rozwiązanie:
public abstract class Employee {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay(Money pay);
}
----------------------
public interface EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
----------------------
public class EmployeeFactoryImpl implements EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
switch (r.type) {
case COMMISSIONED:
return new CommissionedEmployee(r);
case HOURLY:
return new HourlyEmployee(r);
case SALARIED:
return new SalariedEmployee(r);
default:
throw new InvalidEmployeeType(r.type);
}
}
}
Moje pytanie odnosi się właśnie czwartego punktu, czyli zasady otwarty-zamknięty. Jak to, co zaproponował autor ma zapewnić nienaruszanie zasady OCP skoro, przy każdym nowym typie (Next)Employee
trzeba otworzyć klasę EmployeeFactoryImpl
i edytować metodę makeEmployee
?