单一职责原则
1.1 单一职责原则定义
单一职责原则又称单一功能原则,是面向对象的五大基本原则之一。它规定一个类应该只有一个发生变化的原因。
如果开发的一个功能需求不是一次性的,而是随着业务的不断变化而变时,当一个Class类负责超过两个及以上职责时,在需求不断迭代,实现类持续扩张的情况下,就会出现难以维护,不好扩展,测试难度大等问题。
1.2 模拟场景
通过一个视频网站用户分类的例子,来模拟实现单一职责的构建方法,当在各类视频网站看电影、电视时,网站针对不同的用户类型,在用户观看时给出不同的服务反馈,如一下三种。
访客用户,一般只可以观看480P视频,并且时刻提醒用户注册会员才可观看高清视频。
普通会员,可以观看720P超清视频,单不能屏蔽视频中弹出的广告。
VIP会员(属于付费会员),既可以观看1080P蓝光视频,又可以关闭或则跳过广告。
1.3 违背原则方案
下面根据需求场景直接编码,实现一个最简单功能,即根据用户类型,判断用户可以观看的视频类型。
public void serveGrade(String userType){
if ("VIP会员".equals(userType)){
System.out.println("VIP会员,观看1080P蓝光视频");
}else if ("普通会员".equals(userType)){
System.out.println("普通会员,观看720P高清视频");
}else if ("访客用户".equals(userType)){
System.out.println("只可观看480P高清视频");
}
}
}
如上,实现业务逻辑很简单,暂时也不会出什么问题,但是一个类中包含多个不同的行为,也就是多种用户职责,如果在这样的代码上继续扩展功能或者添加逻辑就会显得相当臃肿。
接下来测试代码,查看这个类的功能使用。
public static void main(String[] args) {
VideoUserService videoUserService = new VideoUserService();
videoUserService.serveGrade("VIP会员");
videoUserService.serveGrade("普通会员");
videoUserService.serveGrade("访客用户");
}
}
上面方法的实现方式是在一个if…else中实现,所以调方法时所有职责用户都是使用一个方法实现,作为程序调用入口。对于简单不需要迭代的业务,这种方式也未尝不可,如果面对频繁迭代的业务,此方法将会非常臃肿且难以维护,每次需求的实现都可能影响其他逻辑,给整个接口带来不可控的风险。
1.4 单一职责改善代码
视频播放是视频网站的核心功能,当核心业务开发完,就需要不断迭代完善用户权限,这样才能更好的运行一家视频网站。
在模拟的场景中,其实就是在不断的建设用户权益。针对不同的用户提供差异化服务,技能满足客户需求,又可以让部分用户选择消费。
为了满足这样不断迭代的需求,就不能使用一个类来将所有的职责行为混为一谈,而是提供一个上层接口类,对不同的差异化用户给出单独的实现类,拆分各自的职责。
1.定义接口
public interface IVideoUserService {
//视频清晰级别:480P、720P、1080P
void definition();
//广告播放方式:无广告、有广告
void advertisement();
}
定义出上层接口,同意定义需要实现的功能,包括视频清晰度接口definition()、广告播放方式接口advertisement()。三种不同的用户类型就可以分别实现自己的服务类,做到职责统一。
(1)访客用户实现类。该类用户只可观看视频清晰度为480P的高频视频,同时需要观看广告。
/**
* 访客用户实现类
*/
public class GuestVideoUserService implements IVideoUserService {
@Override
public void definition() {
System.out.println("当前是访问用户,视频清晰度为480P");
}
@Override
public void advertisement() {
System.out.println("访问用户,视频有广告");
}
}
(2) 普通会员实现类。该类用户可以观看视频清晰度为720P的超清视频,同时需要观看广告。
/**
* 普通会员实现类
*/
public class OrdinaryVideoUserService implements IVideoUserService {
@Override
public void definition() {
System.out.println("当前是普通会员用户,视频清晰度为720P");
}
@Override
public void advertisement() {
System.out.println("普通会员,视频有广告");
}
}
(3)VIP会员实现类。该类用户为付费用户,可以观看视频清晰度为1080P的蓝光视频,同时不需要观看广告。
/**
* VIP会员实现类
*/
public class VipVideoUserService implements IVideoUserService {
@Override
public void definition() {
System.out.println("当前是VIP会员用户,视频清晰度为1080P");
}
@Override
public void advertisement() {
System.out.println("VIP会员,视频无广告");
}
}
综上,每种用户对应的服务职责都有对应的实现类,互不干扰。当某一类用户需要添加新的运营规则时,操作起来非常方便,并且不会对其他类用户有任何影响。
接下来测试代码,查看这个类的功能使用。
public static void main(String[] args) {
//访客用户
IVideoUserService guest=new GuestVideoUserService();
guest.definition();
guest.advertisement();
//普通会员
IVideoUserService ordinary=new OrdinaryVideoUserService();
ordinary.definition();
ordinary.advertisement();
//VIP会员
IVideoUserService vip=new VipVideoUserService();
vip.definition();
vip.advertisement();
}
下面为实现类图:
通过单一职责优化代码后,每个类只负责自己的用户行为。后续无论扩展新的需求还是某个时刻修改某个用户行为,都可以非常方便的开发维护。
在实际项目开发中,尽可能保证接口的定义、类的实现及方法保持单一职责,对后期的开发与维护有很大的帮助。