popov . dev

Главная

Библиотека

Статьи

Принципы SOLID

Принципы SOLID

Принципы SOLID - это набор из пяти принципов проектирования, которые помогают создавать удобные в обслуживании и гибкие программные системы. Эти принципы были предложены Робертом К. Мартином (также известным как Дядя Боб) и широко используются в объектно-ориентированном программировании, включая Java. Аббревиатура SOLID расшифровывается как следующие принципы:

  • Single Responsibility Principle (SRP, Принцип единой ответственности)
  • Open-Closed Principle (OCP Принцип "Открыто-закрыто")
  • Leskov’s Substitution Principle (LSP Принцип замещения Лескова)
  • Interface Segregation Principle (ISP Принцип разделения интерфейсов)
  • Dependency Inversion Principle (DIP Принцип инверсии зависимостей)

Принцип единой ответственности (SRP)

У класса должна быть только одна причина для модификаций. Это означает, что у класса должна быть только одна задача и применение или он должен сосредоточиться на том, чтобы хорошо выполнять что-то одно. Придерживаясь этого принципа, вы гарантируете, что у класса будет меньше шансов на изменение по нескольким причинам, что упрощает его понимание, поддержку и тестирование.

// До
class User {
    public void authenticate(String username, String password) {
        // авторизация
    }

    public void updateProfile(User user) {
        // обновление профиля
    }
}

// После
class AuthenticationService {
    public void authenticate(String username, String password) {
        // авторизация
    }
}

class UserProfileService {
    public void updateProfile(User user) {
        // обновление профиля
    }
}

Принцип "Открыто-закрыто" (OCP)

Программные объекты (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации. Этот принцип предполагает, что вы должны разрабатывать свои классы и модули таким образом, чтобы их можно было легко дополнять новыми функциональными возможностями без изменения существующего кода. Это способствует повторному использованию кода и упрощает внедрение новых функций

abstract class Shape {
    public abstract double calculateArea();
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    public double calculateArea() {
        return width * height;
    }
}

// Добавление новой фигуры (Square) без изменения существующего кода
class Square extends Shape {
    private double side;

    public Square(double side) {
        this.side = side;
    }

    public double calculateArea() {
        return side * side;
    }
}

Принцип замещения Лескова (LSP)

Объекты суперкласса должны быть заменяемы объектами его подклассов, не влияя на корректность работы программы. Другими словами, подклассы должны иметь возможность заменять свои базовые (супер) классы, не вызывая неожиданного поведения или не нарушая контракты базового класса. Этот принцип гарантирует, что поведение базового класса сохраняется в его подклассах, и помогает в проектировании иерархий классов.

interface IFlyable {
    void fly();
}

class Bird implements IFlyable {
    public void fly() {
        System.out.println("Птица летает...");
    }
}

class Penguin {
    // Пингвины не умеют летать, поэтому они не реализуют IFlyable
    public void swim() {
        System.out.println("Пингвин плавает...");
    }
}

// Использование LSP
IFlyable bird = new Bird();
bird.fly();

Penguin penguin = new Penguin();
penguin.swim();

Принцип разделения интерфейсов (ISP)

Клиенты не должны зависеть от интерфейсов, которые они не используют. Этот принцип предполагает, что лучше иметь небольшие и более специфичные интерфейсы, а не большие монолитные интерфейсы. Таким образом, вы избегаете создания зависимостей от ненужных методов или функциональных возможностей, а клиенты могут зависеть от интерфейсов, которые имеют к ним отношение. Это способствует ослаблению взаимосвязи и лучшему разделению проблем.

interface Printable {
    void print();
}

interface Scannable {
    void scan();
}

interface Faxable {
    void fax();
}

class AllInOnePrinter implements Printable, Scannable, Faxable {
    public void print() {
        System.out.println("Печать...");
    }

    public void scan() {
        System.out.println("Сканирование...");
    }

    public void fax() {
        System.out.println("Факс...");
    }
}

class BasicPrinter implements Printable {
    public void print() {
        System.out.println("Печать...");
    }
}

// Использование ISP
Printable printer = new BasicPrinter();
printer.print();

Принцип инверсии зависимостей (DIP)

Модули высокого уровня не должны зависеть от модулей низкого уровня. И те, и другие должны зависеть от абстракций. Этот принцип подчеркивает важность использования абстракций (интерфейсов или абстрактных классов), а не конкретных реализаций. Используя абстракции, вы можете разделить модули и сделать их более гибкими и взаимозаменяемыми. Это способствует использованию контейнеров с внедрением зависимостей и инверсией управления (IoC)

interface DataAccess {
    void fetchData();
}

class DatabaseAccess implements DataAccess {
    public void fetchData() {
        System.out.println("Получение данных из базы...");
    }
}

class BusinessService {
    private DataAccess dataAccess;

    public BusinessService(DataAccess dataAccess) {
        this.dataAccess = dataAccess;
    }

    public void doBusinessLogic() {
        // Использование dataAccess для получения данных
        // и выполнение бизнес логики
        dataAccess.fetchData();
        System.out.println("Выполнение бизнес логики...");
    }
}

// Использование DIP
DataAccess dbAccess = new DatabaseAccess();
BusinessService service = new BusinessService(dbAccess);
service.doBusinessLogic();

Почему мы должны использовать принципы SOLID?

  • Это уменьшает зависимости, так что блок кода может быть изменен без ущерба для других блоков кода
  • Принципы, призванные сделать дизайн более простым и понятным
  • Благодаря использованию этих принципов система удобна в обслуживании, тестировании, масштабировании и многократном использовании
  • Это позволяет избежать плохой архитектуры программного обеспечения

Применяя эти принципы, код станет гораздо более понятным, тестируемым и доступным для использования.

Комментарии

Для того чтобы оставить свое мнение, необходимо зарегистрироваться на сайте