单一职责原则
There should never be more than one reason for a class to change.
分析
电话通话的时候有四个过程发生:拨号、通话、回应、挂机,如下所示:
下面是具体代码实现:
/**
* 类描述:
*
* @author:tangniannian
* @date:2016/12/5
* @修改描述:
* @modifier ${tags}
*/
public interface IPhone {
void dial(String phoneNum);
void chat(Object o);
void hangup();
}
上面的代码看起来没有问题,但是单一职责原则要求一个接口或者类只有一个原因引起变化,也就是说一个接口或者类只有一个职责,它就负责一件事,上面的接口显然并不是只负责一件事情。
IPone这个接口可不只是有一个职责,它包含了两个职责:一个是协议管理,一个是数据送达。dial()和hangup()两个方法实现的是协议管理,分别负责拨号和挂机;chat()是实现数据送达。
下面分析上面存在的问题。第一,协议变化显然会造成接口或者类引起变化;第二,数据传送也会造成接口或者类引起变化。
分析发现,上面的接口包含了两个职责,而且两个职责互不影响,所以考虑拆分为两个接口。如下图所示:
// 代码描述
public interface IDataTransfer {
void chat(IConnectionManager iConnectionManager);
}
public interface IConnectionManager {
void dial(String phoneNum);
void hangup();
}
/**
* 类描述:电话具有拨打电话、挂断电话、通话的功能
*
* @修改描述:
* @modifier ${tags}
*/
public class Phone implements IConnectionManager, IDataTransfer{
public void dial(String phoneNum) {
}
public void hangup() {
}
public void chat(IConnectionManager iConnectionManager) {
}
}
总结 单一职责原则优点
- 类的复杂性降低,实现什么职责都有清晰明确的定义;
- 可读性提高,复杂性降低,那当然可读性提高了;
- 可维护性提高,可读性提高,那当然更容易维护了;
- 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
分析
对于接口,我们在设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了。生搬硬套单一职责原则会引起类的剧增,给维护带来非常多的麻烦,而且过分细分类的职责也会人为地增加系统的复杂性。本来一个类可以实现的行为硬要拆成两个类,然后再使用聚合或组合的方式耦合在一起,人为制造了系统的复杂性。