Что такое принципы SOLID?
Ответ от нейросети
sobes.tech AI
SOLID — это набор из пяти основных принципов объектно-ориентированного проектирования, направленных на создание расширяемых, понятных и легко поддерживаемых систем.
-
Single Responsibility Principle (Принцип единственной ответственности): Каждый класс должен иметь только одну причину для изменения. Это означает, что класс должен выполнять только одну четко определенную задачу.
// Нарушение SRP public class Report { public void GenerateReport() { /* ... */ } public void SaveToFile(string filename) { /* ... */ } } // Соблюдение SRP public class ReportGenerator { public void GenerateReport() { /* ... */ } } public class ReportSaver { public void SaveToFile(string filename) { /* ... */ } } -
Open/Closed Principle (Принцип открытости/закрытости): Программные сущности (классы, модули, функции и т. д.) должны быть открыты для расширения, но закрыты для модификации. Это достигается с помощью абстракций (интерфейсов, абстрактных классов).
// Нарушение OCP public class AreaCalculator { public double CalculateArea(object shape) { if (shape is Rectangle r) { return r.Width * r.Height; } else if (shape is Circle c) { return Math.PI * c.Radius * c.Radius; } // придется изменять класс при добавлении новой фигуры return 0; } } // Соблюдение OCP public interface IShape { double CalculateArea(); } public class Rectangle : IShape { public double Width { get; set; } public double Height { get; set; } public double CalculateArea() { return Width * Height; } } public class Circle : IShape { public double Radius { get; set; } public double CalculateArea() { return Math.PI * Radius * Radius; } } public class NewAreaCalculator { public double CalculateArea(IShape shape) { return shape.CalculateArea(); // можно добавлять новые фигуры, не меняя этот класс } } -
Liskov Substitution Principle (Принцип подстановки Лисков): Подтипы должны быть заменяемы своими базовыми типами без нарушения работоспособности программы. Это означает, что производный класс должен полностью соответствовать контракту своего базового класса.
// Нарушение LSP public class Rectangle { public virtual int Width { get; set; } public virtual int Height { get; set; } } public class Square : Rectangle { public override int Width { get { return base.Width; } set { base.Width = base.Height = value; } // Нарушается контракт Rectangle } public override int Height { get { return base.Height; } set { base.Width = base.Height = value; } // Нарушается контракт Rectangle } } // Соблюдение LSP (может потребоваться перепроектирование иерархии) // Или использовать фабричный метод для создания правильных типов -
Interface Segregation Principle (Принцип разделения интерфейсов): Клиентам не следует зависеть от интерфейсов, которые они не используют. Большие монолитные интерфейсы следует разделять на более мелкие и специфические.
// Нарушение ISP public interface IMultiFunctionPrinter { void Print(string document); void Scan(string document); void Fax(string document); } public class SimplePrinter : IMultiFunctionPrinter { public void Print(string document) { /* ... */ } public void Scan(string document) { throw new System.NotImplementedException(); } // Не нужно сканирование public void Fax(string document) { throw new System.NotImplementedException(); } // Не нужен факс } // Соблюдение ISP public interface IPrinter { void Print(string document); } public interface IScanner { void Scan(string document); } public interface IFax { void Fax(string document); } public class NewSimplePrinter : IPrinter { public void Print(string document) { /* ... */ } } -
Dependency Inversion Principle (Принцип инверсии зависимостей):
- Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
// Нарушение DIP public class LightBulb { public void TurnOn() { /* ... */ } public void TurnOff() { /* ... */ } } public class ElectricPowerSwitch { private LightBulb bulb; public ElectricPowerSwitch(LightBulb bulb) { this.bulb = bulb; // Прямая зависимость от конкретной реализации LightBulb } public void Press() { // ... } } // Соблюдение DIP public interface ISwitchable { void TurnOn(); void TurnOff(); } public class NewLightBulb : ISwitchable { public void TurnOn() { /* ... */ } public void TurnOff() { /* ... */ } } public class NewElectricPowerSwitch { private ISwitchable device; public NewElectricPowerSwitch(ISwitchable device) { this.device = device; // Зависимость от абстракции ISwitchable } public void Press() { // ... } }