Zasada segregacji interfejsów

"Dochodzenie do mistrzostwa wymaga dwóch elementów: wiedzy i pracy." - Robert C. Martin

Zasada segregacji interfejsów

Zasada segregacji interfejsów

Zasada segregacji interfejsów głosi, że interfejsy powinny być małe i konkretne, tak by klasy nie implementowały metod, których nie potrzebują. Zasada ta ma w szczególności za zadanie wyeliminowanie nieporęcznych, niepotrzebnie rozbudowanych interfejsów. Każdy interfejs zgodnie z tą zasadą powinien zostać podzielony na mniejsze grupy metod. Przedstawiony poniżej program dla automatu z kawą łamie zasadę ISP, gdyż jeden interfejs CoffeeMaker zawiera metody, które nie są w całości stosowane przez wszystkie klasy implementujące ten interfejs. Przygotownie kawy Americano nie wymaga metod takich jak addMilk() oraz addFrothyMilk(), tak jak przygotowanie kawy LatteMacchiato nie wymaga metody addWater(). Natomiast przygotowanie obu tych kaw wymaga metod prepareEspresso() oraz spendCup(). Stosowanie jednego złożonego interfejsu powoduje, że każda z klas implementująca interfejs musi zaimplementować wszystkie metody interfejsu, nawet te, które nie są potrzebne. Najlepszym rozwiązaniem dla tego przypadku będzie podzieleniu jednego złożonego interfejsu na kilka mniejszych. Klasy Americano i LatteMacchiato będą implementowały jeden wspólny interfejs zawierający metody prepareEspresso() oraz spendCup(). Dodatkowo każda z klas  będzie implementowała jedne interfejs specyficzny, w przypadku klasy Americano będzie to interfejs AmericanoPreparing, zaś w przypadku kawy LatteMacchiato będzie to interfejs LatteMacchiatoPreparing.

interface CoffeeMaker
{
public function prepareEspresso();
public function addWater();
public function addMilk();
public function addFrothyMilk();
public function spendCup();
}

class LatteMacchiato implements CoffeeMaker
{
public function prepareEspresso()
{
echo 'Parzę kawę...<br />';
}

public function addWater()
{
}

public function addMilk()
{
echo 'Dodaję mleko...<br />';
}

public function addFrothyMilk()
{
echo 'Dodaję spienione mleko...<br />';
}

public function spendCup()
{
echo 'Kawa gotowa! Odbierz kubek..<br />';
}
}

class Americano implements CoffeeMaker
{
public function prepareEspresso()
{
echo 'Parzę kawę...<br />';
}

public function addWater()
{
echo 'Dolewam gorącej wody...<br />';
}

public function addMilk()
{
}

public function addFrothyMilk()
{
}

public function spendCup()
{
echo 'Kawa gotowa! Odbierz kubek...<br />';
}
}

$order = new LatteMacchiato();
$order -> prepareEspresso();
$order -> addWater();
$order -> addMilk();
$order -> addFrothyMilk();
$order -> spendCup();

Poprawiony i zgodny z regułą ISP kod źródłowy dla programu obsługującego automat z kawą wygląda następująco:

 
interface CoffeeMaker 
{
public function prepareEspresso();
public function spendCup(); 
}

interface LatteMacchiatoPreparing 
{ 
public function addMilk(); 
public function addFrothyMilk();
}

interface AmericanoPreparing 
{ 
public function addWater(); 
}

class LatteMacchiato implements CoffeeMaker, LatteMacchiatoPreparing 
{
public function prepareEspresso()
{
echo 'Parzę kawę...<br />';
}

public function addMilk()
{
echo 'Dodaję mleko...<br />';
}

public function addFrothyMilk()
{
echo 'Dodaję spienione mleko...<br />';
}

public function spendCup()
{
echo 'Kawa gotowa! Odbierz kubek...<br />';
}
}

class Americano implements CoffeeMaker, AmericanoPreparing
{
public function prepareEspresso()
{
echo 'Parzę kawę...<br />';
}

public function addWater()
{
echo 'Dolewam gorącej wody...<br />';
}

public function spendCup()
{
echo 'Kawa gotowa! Odbierz kubek...<br />';
}
}

$order = new Americano();
$order -> prepareEspresso();
$order -> addWater();
$order -> spendCup();