Similar presentations:
SOLID
1.
Принципы проектированияСоздание гибких и расширяемых программ
Упрощение тестирования и поддержки
Носят *рекомендательный характер
2.
SOLIDS — Single Responsibility Principle
O — Open/Closed Principle
L — Liskov Substitution Principle
I — Interface Segregation Principle
D — Dependency Inversion Principle
3.
Single Responsibility PrincipleПринцип единственной ответственности
Каждый отдельный класс должен
специализироваться только на решении
одной узкой задачи
4.
Доclass Order {
public void calculateTotalSum() { }
public void getItems() { }
public void addItem(Item item) { }
public void printOrder() { }
}
5.
Доclass Order {
public void calculateTotalSum() { }
public void getItems() { }
public void addItem(Item item) { }
public void printOrder() { } // Куда? Как?
}
6.
ПроблемаКласс ответственен и за хранение данных, и
за их внешнюю обработку
При желании изменить способ печати
придется менять класс Order
7.
Послеclass Order {
public void calculateTotalSum() { }
public void getItems() { }
public void addItem(Item item) { }
}
// Каждый класс ответственен только за ограниченный набор задач
class OrderPrinter {
public void printOrder(Order order) { }
}
8.
The Open/Closed PrincipleПринцип открытости/закрытости
Программные сущности должны быть
открыты для расширения, но закрыты для
модификации.
9.
Доclass AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Rectangle) {
// some calculations
}
else if (shape instanceof Circle) {
// some calculations
}
10.
Доclass AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Rectangle) {
// some calculations
}
else if (shape instanceof Circle) {
// some calculations
}
11.
ПроблемаПри добавлении новых сущностей придется
изменять уже написанный код
12.
Послеinterface Shape {
double calculateArea();
} // Закрытая для модификации абстракция
class Rectangle implements Shape {
@Override
public double calculateArea() { }
} // Конкретные расширяемые реализации
class Circle implements Shape {
@Override
public double calculateArea() { }
} // Конкретные расширяемые реализации
13.
The Liskov Substitution PrincipleПринцип подстановки Барбары Лисков
Объекты в программе должны быть
заменяемыми на экземпляры их подтипов
без изменения правильности выполнения
программы.
14.
Доclass Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
class Square extends Rectangle {
@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width);
}
@Override
public void setHeight(int height)
{
super.setHeight(height);
15.
Доclass Rectangle {
protected int width;
protected int height;
class Square extends Rectangle {
@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width);
} // Меняется логика родителя
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
@Override
this.height = height;
public void setHeight(int height)
}
{
public int getArea() {
super.setHeight(height);
16.
public class Test {public static void main(String[ ] args) {
Rectangle rectangle = new Square();
rectangle.setWidth(5);
rectangle.setHeight(10);
System.out.println(rectangle.getArea());
} // Ожидаем площадь 50, но по факту 100
}
17.
Послеinterface Shape {
int getArea();
}
class Rectangle implements Shape {
// some methods
}
class Square implements Shape {
// some methods
}
18.
The Interface Segregation PrincipleПринцип разделения интерфейса
Много специализированных интерфейсов
лучше, чем один универсальный
Клиенты не должны зависеть от методов,
которые они не используют.
19.
Доinterface Unit {
void heal();
void defend();
void attack();
}
class Healer implements Unit {
public void heal() { }
public void defend() {
throw new UnsupportedActionException("healers have no
protection!");
20.
Доinterface Unit {
void heal();
void defend();
void attack();
} // Интерфейс, который отвечает за все возможные действия
юнитов
class Healer implements Unit {
public void heal() { }
public void defend() {
throw new UnsupportedActionException("healers have no
21.
Проблема«Толстый» интерфейс
Классы отвечают за те методы, которые не
используют
22.
После// Несколько небольших специфичных интерфейсов
interface Healing {
void heal();
class Knight implements Defendable, Fightable {
}
void fight();
void defend();
interface Defendable {
}
void defend();
}
interface Fightable {
void fight();
}
class Healer implements Healing {
23.
The Dependency Inversion PrincipleМодули верхнего уровня не должны зависеть
от модулей нижнего уровня. И те, и другие
должны зависеть от абстракций
Абстракции не должны зависеть от деталей.
Детали должны зависеть от абстракций
24.
class GamingMouse {void click();
}
До
class Computer {
private GamingMouse mouse;
public Computer() {
this.mouse = new GamingMouse();
}
public void work() {
25.
Доclass GamingMouse {
void click();
} // Реализация конкретной мышки
class Computer {
private GamingMouse mouse; // А если захотим использовать
другую мышь? Имеется прямая зависимость
public Computer() {
this.mouse = new GamingMouse(); // Привязаны к конкретной
сущности
}
26.
ПроблемаЕсли понадобится использовать другие
детали, то придется переделывать класс,
зависящий от этих деталей
27.
Послеinterface Mouse {
void click();
}
class GamingMouse implements Mouse {
void click(){ };
} // Конкретные устройства реализуют интерфейс
class WirelessMouse implements Mouse {
void click(){ };
} // Конкретные устройства реализуют интерфейс
28.
Послеclass Computer {
private Mouse mouse; // зависимость от интерфейса, а не от
деталей
public Computer(Mouse mouse){
this.mouse = mouse;
}
public void work() {
mouse.click();
}