Принцип единой ответственности — это первый принцип из сплошной аббревиатуры.
«У класса должна быть только одна причина измениться».
Каждый модуль или класс должен нести ответственность за одну часть функциональности, предоставляемой программным обеспечением, и эта ответственность должна быть полностью заключена в класс.
Например, представьте сценарий навигационного программного обеспечения.
У нас есть позиция, которая в зависимости от заданного направления (север, юг, запад, восток) должна измениться.
Класс 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, являются их собственными. |