SOLID - IsuiGit/borodaedu GitHub Wiki
SOLID - это набор пяти принципов ООП проектирования, которые помогают создавать более гибкие, поддерживаемые и масштабируемые системы.
Single responsibility principle (принцип единственности ответственности). Принцип SRP гласит о том, что у класса должна быть только одна причина для изменения, т.е. он должен иметь только одну ответственность.
//class User {
//public:
// void setName();
// std::string getName();
// void print(); // <- обязует каждый объект класса User предоставлять интерфейс
// // вывода данных о пользователе внутри себя.
//private:
// std::string name;
//};
class User {
public:
void setName(std::string name) { this->name = name; };
std::string getName() { return name; };
private:
std::string name;
};
class Interface {
public:
static void printUser(User& user) {
std::cout << user.getName() << std::endl;
};
};
int main() {
User u;
u.setName("ORKADIY");
Interface::printUser(u);
}Open/Closed principle (принцип открытости/закрытости) утверждает, что классы должны быть открыты для расширения, но закрыты для модификации. Это означает, что поведение класса можно изменять, не меня его исходный код.
class Shape {
public:
Shape() { ++count; }
static int getCount() { return count; }
virtual double area() const = 0; // Абстрактный метод вычисления площади
private:
inline static int count = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius(radius) {}
double area() const override {
return 3.14 * radius * radius;
}
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) :width(width), height(height) {}
double area() const override {
return width * height;
}
private:
double width, height;
};
int main() {
Circle c(10.0);
Rectangle r(5.0, 3.0);
std::cout << c.area() << std::endl;
std::cout << r.area() << std::endl;
std::cout << Shape::getCount() << std::endl;
}Принцип подстановки Лисков гласит, что объекты подкласса должны быть взаимозаменяемыми с объектами базового класса без изменения правильности программы.
// Пример нарушения LSP
//class Bird {
//public:
// virtual void fly() const{ /* птица летает */ }
//};
//
//class Sparrow : public Bird {
//public:
// void fly() const override {}
//};
//
//class Ostrich : public Bird {
// void fly() const override {
// throw std::runtime_error("Страусы не летают!");
// }
//};
class Flyable { // <- отдельный класс для "летательных" объектов
virtual void fly() const {}
};
class Walkable { // <- отдельный класс для "ходительных" объектов
virtual void walk() const {}
};
class Sparrow : public Flyable, public Walkable { //<- наследуется от всех классов
public:
void fly() const override {}
void walk() const override {}
};
class Ostrich : public Walkable { // <- наследуется только от необходимых классов
public:
void walk() const override {}
};Interface Segregation Principle (принцип разделения интерфейса) утверждает, что клиенты не должны зависеть от интерфейсов, которые они используют. Это означает, что лучше иметь несколько специализированных интерфейсов, чем один универсальный.
// Ай как хорошо!
class Printer {
public:
virtual void print() = 0;
};
class Scanner {
public:
virtual void scan() = 0;
};
class MultiFucntionalPrint : public Printer, public Scanner {
public:
void print() override {}
void scan() override {}
};
// Очень плохо!
class MultiCoolSuperDuperPrinter2007 {
public:
void do_smth(int type) {
if (type == 1) {
CosmicCoolPrint();
}
else if (type == 2) {
MegaScan()
}
else if (type != 1 && type != 2) {
panic!();
}
else {
call_to_sysadmin();
}
}
};
Dependency Inversion Principle (принцип инверсии зависимостей) гласит, что высокоуровневые модули не должны зависеть от низкоуровневых, а оба должны зависеть от абстракций. Также абстракции не должны зависеть от деталей, а детали должны зависеть от абстракций.
#include <iostream>
class IMessageSender {
public:
virtual void sendMessage(const std::string& message) = 0;
};
class EmailSender : public IMessageSender {
void sendMessage(const std::string& message) override {}
};
class PushSender : public IMessageSender {
void sendMessage(const std::string& message) override {}
};
class Notification {
private:
IMessageSender& messageSender;
public:
Notification(IMessageSender& sender) : messageSender(sender) {}
void notify(const std::string& message) {
messageSender.sendMessage(message);
}
};
int main() {
EmailSender es;
PushSender ps;
Notification notif(ps);
}