Принцип единой ответственности — это первый принцип из сплошной аббревиатуры.
«У класса должна быть только одна причина измениться».
Каждый модуль или класс должен нести ответственность за одну часть функциональности, предоставляемой программным обеспечением, и эта ответственность должна быть полностью заключена в класс.
Например, представьте сценарий навигационного программного обеспечения.
У нас есть позиция, которая в зависимости от заданного направления (север, юг, запад, восток) должна измениться.
Класс Position содержит значения, касающиеся положения оси x и y.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.gkatzioura.solid.single;public class Position { private Integer xAxis; private Integer yAxis; public Position(Integer xAxis, Integer yAxis) { this.xAxis = xAxis; this.yAxis = yAxis; } public Integer getxAxis() { return xAxis; } public void setxAxis(Integer xAxis) { this.xAxis = xAxis; } public Integer getyAxis() { return yAxis; } public void setyAxis(Integer yAxis) { this.yAxis = yAxis; }} |
Направление является enum, представляющим направление на север, восток, юг и запад.
|
1
2
3
4
5
|
package com.gkatzioura.solid.single;public enum Direction { N,W,S,E} |
И наконец, есть класс Navigator, который отвечает за навигацию в соответствии с изменением направления и положения.
|
1
2
3
4
5
6
7
|
public class Navigator { public Position navigate(Position position, Direction direction) { .... }} |
Для правильной навигации навигатор должен определить следующую позицию в зависимости от направления. Также навигатор должен зафиксировать положение в случае значений ниже 0.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class Navigator { public Position navigate(Position position, Direction direction) { Position nextPosition = resolve(position,direction); Position fixedPosition =fix(nextPosition); return fixedPosition; } public Position resolve(Position position,Direction direction) { switch (direction) { case N: return new Position(position.getxAxis(),position.getyAxis()+1); case S: return new Position(position.getxAxis(),position.getyAxis()-1); case W: return new Position(position.getxAxis()-1,position.getyAxis()); case E: return new Position(position.getxAxis()+1,position.getyAxis()); default: throw new IllegalArgumentException(); } } public Position fix(Position position) { return new Position( position.getxAxis()<0?0:position.getxAxis(), position.getyAxis()<0?0:position.getyAxis() ); }} |
Проблема этого подхода заключается в том, что в случае изменения критериев достоверности позиции мы должны изменить класс навигатора. То же самое относится и к смене механизмов перемещения позиции. Навигатор вместо простой навигации отвечает как за определение следующей позиции, так и за фиксацию новой позиции.
Подход, который не нарушает принцип единой ответственности, заключается в создании класса, который разрешит следующую позицию, и класса, ответственного за фиксацию новой позиции.
Класс NextPositionResolver разрешит следующую позицию в зависимости от заданного направления.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.gkatzioura.solid.single;public class NextPositionResolver { public Position resolve(Position position,Direction direction) { switch (direction) { case N: return new Position(position.getxAxis(),position.getyAxis()+1); case S: return new Position(position.getxAxis(),position.getyAxis()-1); case W: return new Position(position.getxAxis()-1,position.getyAxis()); case E: return new Position(position.getxAxis()+1,position.getyAxis()); default: throw new IllegalArgumentException(); } }} |
Класс PositionRepairer исправит положение в случае недопустимых значений x или y.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
package com.gkatzioura.solid.single;public class PositionRepairer { public Position fix(Position position) { return new Position( position.getxAxis()<0?0:position.getxAxis(), position.getyAxis()<0?0:position.getyAxis() ); }} |
Класс Navigator будет иметь в качестве зависимостей классы NextPositionResolver и PositionRepairer для правильного выполнения навигации.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package com.gkatzioura.solid.single;public class Navigator { private NextPositionResolver nextPositionResolver; private PositionRepairer positionRepairer; public Navigator(NextPositionResolver nextStepResolver,PositionRepairer positionRepairer) { this.nextPositionResolver = nextStepResolver; this.positionRepairer = positionRepairer; } public Position navigate(Position position, Direction direction) { Position nextPosition = nextPositionResolver.resolve(position,direction); Position fixedPosition = positionRepairer.fix(nextPosition); return fixedPosition; }} |
Вы можете найти исходный код на github . Следующий принцип — открытый / закрытый принцип.
Также я составил шпаргалку, содержащую краткое изложение основных принципов.
Зарегистрируйтесь в ссылке, чтобы получить его.
| Опубликовано на Java Code Geeks с разрешения Эммануила Гкациоураса, партнера нашей программы JCG. Смотреть оригинальную статью здесь: Твердые принципы: принцип единой ответственности
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |