您的位置:首页 > 编程语言 > Java开发

Java设计模式中单一职责原则(SRP)介绍

2017-07-25 08:35 609 查看
原文地址:http://blog.csdn.net/qq_24451605/article/details/51346786


单一职责原则(Single Responsibility Principle)


SRP 基本概念

单一职责原则
定义:应该有且仅有一个原因引起类的变更,也就是接口或类和职责的关系是一一对应的。
难点:职责的划分: 
在不同情景和生产环境下我们对职责的细化是不同的(职责单一的相对性)
单一职责原则提出的是一个评价接口是否优良的标准,但是职责和变化原因是不可度量的,因项目而异,因环境而异(不可度量性)

优势: 
类的复杂性降低:每个类或接口都只实现单一的职责,定义明确清晰
可读性提高:定义明确清晰,自然带来较高的代码可读性
可维护性提高:代码可读性强,更容易理解,自然方便维护,而且职责单一所以类之间耦合度较低,所以更容易修改。
拓展性更好:有新的职责需要拓展,只需要继承对应的接口实现新的实现即可。


例讲SRP

因为面向对象的编程是推崇面向接口的编程的,我们对外暴露的方法也最好是以接口的形式定义,再由具体的类进行实现,诸多的好处就不再赘述,我们下面就基于一个简单的场景进行设计,体现单一职责的好处:


场景的定义

比如Pear是一家电子产品商,它要生产pad,phone,watch等设备,但是有一些重复的功能,如果分别设计一套,很显然并不划算,那么接口定义上我们就可以根据功能划分设定单一职责的接口:


接口的定义

//可以拨打电话
interface Callable{
void call ();
}

//可以触摸控制
interface Touchable{
void touch();
}

//可以消息提醒
interface MessagePromptable{
void prompt();
}

//可以接入键盘
interface KeyBoardMatchable{
void match();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


实现接口的类依旧单一职责

class StandardCall implements Callable{

@Override
public void call() {
System.out.println("Call to somebody!");
}
}

class StandardTouch implements Touchable{

@Override
public void touch() {
System.out.println("touch to press the button!");
}
}

class StandardPromt implements MessagePromptable{

@Override
public void prompt() {
System.out.println(" someone contact to you,sir!");
}
}

class StandardMatch implements KeyBoardMatchable{

@Override
public void match() {
System.out.println("The keyBoard is ready to work!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


产品的生产

我们如果基于我们现有的技术生产一部手机,那么我们需要它能打电话,触屏控制和消息提醒:
//在声明这台手机时我们就明确知道了它的功能
class MyPhone implements Callable,MessagePromptable,Touchable{

//无需重复研发已有的技术,直接装载即可
private Callable caller = new StandardCall();
private MessagePromptable prompter = new StandardPromt();
private Touchable toucher = new StandardTouch();

@Override
public void call() {
caller.call();
}

@Override
public void prompt() {
prompter.prompt();
}

@Override
public void touch() {
toucher.touch();
}
}

public class SRPTest {
public static void main ( String [] args ){
MyPhone phone = new MyPhone();
phone.call();
phone.prompt();
phone.touch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
假如我们需要出一款新的手机,但是我们只是拥有了新的呼叫技术,那么只需要在实现这项技术时继承Callable接口,然后在之前手机的Callable的具体是凶案类换成新的技术即可,只需要修改一行代码,是不是感觉棒棒的。职责的单一,对于我们对于现有类的修改造成的影响有了约束
那么如果我想生产一个Pad呢,同理啊,只需要在已有技术上装载即可啊,Pad类依旧只是单一的整合技术形成产品的职责,整合成产品和研发出技术的职责分离,为我们的类的拓展带来了方便
class MyPad implements Touchable,KeyBoardMatchable{

Touchable toucher = new StandardTouch();
KeyBoardMatchable matcher = new StandardMatch();

@Override
public void match() {
toucher.touch();
}

@Override
public void touch() {
matcher.match();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


总结

通过上面额例子,可以有一个更清晰的理解,其实如果单个接口都提供一个实现类会导致类额数量很庞大,使用起来很不方便,所以我们可以整合一些功能。简而言之:


对于单一职责原则,接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化

下面一个例子,我们的接口依旧单一职责,但是接听和拨打电话的功能往往是不可分的,他们会同时发生变化,所以我们可以提供一个同时继承两个接口的实现类。
class CallAndPrompt implements Callable,MessagePromptable{

@Override
public void call() {
System.out.println("Hello, I have some thing to tell you!");
}

@Override
public void prompt() {
System.out.println("Hello,what do you want to tell me!");
}
}

//在声明这台手机时我们就明确知道了它的功能
class MyPhone implements Callable,MessagePromptable,Touchable{

//无需重复研发已有的技术,直接装载即可
private Callable caller = new CallAndPrompt();
//不同的接口调用同一个实现类的不同功能
private MessagePromptable prompter = (MessagePromptable)caller;
private Touchable toucher = new StandardTouch();

@Override
public void call() {
caller.call();
}

@Override
public void prompt() {
prompter.prompt();
}

@Override
public void touch() {
toucher.touch();
}
}
1
2
3
4
5
6
7
8
9
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
35
36
37
1
2
3
4
5
6
7
8
9
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
35
36
37

从上面的例子,可能你会更理解我的总结。但是原则这个东西要遵守,但是没必要死守。在实际的设计中还是要学会变通。毕竟经典的设计模式也不总是遵守这些设计原则,但他们依旧被广泛地应用到实际当中,而且表现还不错
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: