定义:不要存在多于一个导致类变更的原因。
一个类/接口/方法只负责一项职责。
优点:降低类的复杂度、提升类的可读性,提高系统的可维护性、降低变更引起的风险。
案例:
(1)类职责隔离
此处以鸟的移动模式举例,V1版本代码如下
public class Bird { public void mainMoveMode(String birdName){ System.out.println(birdName+"用翅膀飞"); } }
上述的代码中,对于普通的鸟是适合的,但是假如是鸵鸟,鸵鸟用翅膀飞,显然是不合理的。所以此方法既有用脚走的,又有用翅膀飞的, 不符合单一职责的原则。
在日常的开发中,也经常会碰到这种业务需要做一些调整的时候,上述场景下我们经常会如下调整
public class Bird { public void mainMoveMode(String birdName){ if("鸵鸟".equals(birdName)){ System.out.println(birdName+"用脚走"); }else{ System.out.println(birdName+"用翅膀飞"); } } }
这样是可以满足要求的,但是实际的业务场景中如果判断的条件非常多,边界也更复杂的情况,就会面临后期难以维护的情况。
此时,可以使用单一职责进行拆分,在类的层次上将职责进行拆分,V2版本代码如下
public class FlyBird { public void mainMoveMode(String birdName){ System.out.println(birdName+"用翅膀飞"); } }
public class WalkBird { public void mainMoveMode(String birdName){ System.out.println(birdName+"用脚走"); } }
public class Test { public static void main(String[] args) { // Bird bird = new Bird(); // bird.mainMoveMode("大雁"); // bird.mainMoveMode("鸵鸟"); FlyBird flyBird = new FlyBird(); flyBird.mainMoveMode("大雁"); WalkBird walkBird = new WalkBird(); walkBird.mainMoveMode("鸵鸟"); } }
(2)接口职责隔离
上述是类层面上单一职责的案例,下面再举一个接口层面的单一职责。
我们以网课为例,V1代码如下,可能的接口中,既有可能基本信息的方法,又有学习课程,课程退款等方法,这几个方法之间有可能会互相影响,职责划分有不是很清晰。如退款了之后,是无法获得到课程基本信息的,也无法进行学习的。
public interface ICourse { String getCourseName(); byte[] getCourseVideo(); void studyCourse(); void refundCourse(); }
针对上述问题,我们将接口职责进行划分,这样的话,从接口层面进行了职责的隔离,职责更加清晰,降低了维护的复杂度,实现类可以通过实现多个职责的接口,组合出想要的具体实现,更加的灵活,V2版本如下,
public interface ICourseContent { String getCourseName(); byte[] getCourseVideo(); }
public interface ICourseManager { void studyCourse(); void refundCourse(); }
public class CourseImpl implements ICourseManager,ICourseContent { @Override public void studyCourse() { } @Override public void refundCourse() { } @Override public String getCourseName() { return null; } @Override public byte[] getCourseVideo() { return new byte[0]; } }
(3)方法职责隔离
日常的开发中,我们呢经常会写一些增删改查的操作,此处我以更新用户的基本信息为例,updateUserInfo方法中,通过判断来更新用户名或者是用户地址,此处,我们就可以将该方法进行拆分,将更新用户名和地址拆分两个方法,让应用层来决定更新什么操作。
public class Method { private void updateUserInfo(String userName,String address){ userName = "Galen"; address = "beijing"; } private void updateUserInfo(String userName,String... properties){ userName = "Galen"; // address = "beijing"; } private void updateUsername(String userName){ userName = "Galen"; } private void updateUserAddress(String address){ address = "beijing"; } private void updateUserInfo(String userName,String address,boolean bool){ if(bool){ //todo something1 }else{ //todo something2 } userName = "Galen"; address = "beijing"; } }