SOLID – Zasada Segregacji Interfejsów
W tym wpisie przedstawię Ci, czym jest zasada segregacji interfejsów. Jest to 4 zasada z 5 mnemonika SOLID.
I literka I na naszej liście. Co oznacza, że w tym wpisie przedstawię Ci zasadę segregacji interfejsów. No właśnie, czym jest zasada segregacji interfejsów?
SOLID
S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP)
O – Zasada otwarte – zamknięte – (Open-Closed Principle – OCP)
L – Zasada podstawiania Liskov – (Liskov Substitution Principle – LSP)
I – Zasada segregacji interfejsów – (Interface Segregation Principle – ISP)
D – Zasada odwracania zależności – (Dependency Inversion Principle DIP)
Zasada Segregacji Interfejsów
Podstawą rozważań na temat tej zasady są interfejsy. Poprzez interfejs możemy rozumieć klasę abstrakcyjną z metodami abstrakcyjnymi lub zwykły interfejs. W niniejszym artykule będę posługiwał się terminem interfejs, mając na myśli obie te rzeczy.
Podczas implementacji interfejsie jesteśmy zmuszeni do zaimplementowania każdej jego składowej. Czy zdarzyło Ci się, że korzystając z jakiegoś interfejsu w nowo tworzonej klasie, nie wypełniłeś ciała którejś z jego metod? Jeżeli tak, to naruszyłeś zasadę segregacji interfejsu. A mówi ona:
Załóżmy, że implementujesz interfejs. Jeśli zauważysz, że się, że jakaś metoda lub propercja nie jest Ci w niej potrzebna i implementacja jest pusta/domyślna, to w takim przypadku powinieneś przemyśleć strukturę tego interfejsu. W takim przypadku błędnie zaprojektowałeś hierarchię. Powinieneś dokonać podziału tego interfejsu na kilka mniejszych.
Praktyczny przykład
Wszystko łatwiej zrozumieć na przykładzie. Posłużę się lekko zmodyfikowanym kodem z poprzedniego wpisu o mnemoniku SOLID.
public interface IVehicle
{
double Combustion { get; set; }
string Name { get; set; }
int WheelsCount { get; set; }
void About();
}
public class Car : IVehicle
{
public string Type { get; set; }
public double Combustion { get; set; }
public string Name { get; set; }
public int WheelsCount { get; set; }
public void About()
{
Console.WriteLine($"I'm {Type} - {Name} - with {Combustion}L combustion and {WheelsCount} wheels count!");
}
}
public class ElectricCar : IVehicle
{
public int BatteriesCount { get; set; }
public void About()
{
Console.WriteLine($"I'm {Name} - with {WheelsCount} wheels count and {BatteriesCount} batteries count!");
}
public double Combustion { get; set; }
public string Name { get; set; }
public int WheelsCount { get; set; }
}
internal class Program
{
private static void Main()
{
var electricCar = new ElectricCar();
var car = new Car();
car.Name = "Tesla";
car.WheelsCount = 4;
car.Type = "Muscle Car";
car.Combustion = 10.5f;
electricCar.Name = "Tesla";
electricCar.WheelsCount = 4;
electricCar.BatteriesCount = 10;
electricCar.About();
car.About();
Console.WriteLine();
Console.ReadKey();
}
}
Wszystko działa poprawnie. Zwróć, proszę uwagę na kod programu, a dokładnie na klasę ElectricCar
. Właściwość Combustion
musi zostać zaimplementowana mimo że nie będzie używana. Rozwiążmy ten problem.
Sposobów na poprawienie tego problemu jest wiele. Jednym z nich jest utworzenie nowego interfejsu dla pojazdów elektrycznych dziedziczący po IVehicle
, ale przedtem należy zmodyfikować ten interfejs.
public interface IVehicle
{
string Name { get; set; }
int WheelsCount { get; set; }
void About();
}
public interface IElectricVehicle : IVehicle
{
int BatteriesCount { get; set; }
}
public class Car : IVehicle
{
public string Type { get; set; }
public double Combustion { get; set; }
public string Name { get; set; }
public int WheelsCount { get; set; }
public void About()
{
Console.WriteLine($"I'm {Type} - {Name} - with {Combustion}L combustion and {WheelsCount} wheels count!");
}
}
public class ElectricCar : IElectricVehicle
{
public string Name { get; set; }
public int WheelsCount { get; set; }
public int BatteriesCount { get; set; }
public void About()
{
Console.WriteLine($"I'm {Name} - with {WheelsCount} wheels count and {BatteriesCount} batteries count!");
}
}
internal class Program
{
private static void Main()
{
var electricCar = new ElectricCar();
var car = new Car();
car.Name = "Tesla";
car.WheelsCount = 4;
car.Type = "Muscle Car";
car.Combustion = 10.5f;
electricCar.Name = "Tesla";
electricCar.WheelsCount = 4;
electricCar.BatteriesCount = 10;
electricCar.About();
car.About();
Console.WriteLine();
Console.ReadKey();
}
}
Przykład, choć naiwny przedstawił główne założenie, jakie ze sobą niesie zasada segregacji interfejsu.