今天的博客主题
设计原则和模式 --》设计原则之单一职责原则
单一职责原则 SRP (Simple Responsibility Pinciple)
是说不要存在多于一个导致类变更。
怎么说呢,就是一个类负责两个任务,一个任务变更,修改这个任务逻辑代码,有可能会导致另一个任务发生意外。
这样一来,那找个类就存在两个导致类变更的原因。
如何解决这个问题呢?那就给这两个任务分开,分到两个类里面去,进行解耦。
后期任务变更互不影响。
达到了 降低类的复杂度,提高类的可读性,提高了系统的维护性,降低变更引起的风险。
总的说就是一个 类、接口或方法只负责一个功能模块。
代码示例:
继续使用销售类,对于每个手机利润是不一样的,厂家给的优惠价以及手机进价,或者做活动时候的价格都不一样。
对于这些功能需求,随时可能都会调整的。
新建一个 Sale 类
public class Sale {
public void salePhone(String phone, Double price){
if("Apple".equals(phone)){
System.out.println(phone + " 销售价:" + price);
}else if("HuaWei".equals(phone)){
System.out.println(phone + " 销售价:" + price);
}
}
}
调用
public class DemoSRP {
public static void main(String[] args) {
Sale sale = new Sale();
sale.salePhone("Apple", 1888.00);
sale.salePhone("HuaWei", 1889.00);
}
}
输出
Apple 销售价:1888.0
HuaWei 销售价:1889.0
从上述代码可以看出 Sale 类,承担了两个职责任务。
现在 618 了,活动价,有优惠卷等等。每个手机优惠不一样,优惠卷满多少才可以用。
这就得改代码了。修改代码就势必会相互影响,造成不可控的风险。
这个时候方法就很臃肿,参数增加,折扣,优惠卷,逻辑控制层继续增加逻辑判断,代码长,维护性,可读性极差。
重构调整代码===》
对职责功能进行分离解耦,新建 SaleHuaWeiPhone 和 SaleApplePhone
public class SaleApplePhone {
public void sale(String phone, Double price){
System.out.println(phone + " 销售价:" + price);
}
}
public class SaleHuaWeiPhone {
public void sale(String phone, Double price){
System.out.println(phone + " 销售价:" + price);
}
}
调用
public static void main(String[] args) {
SaleApplePhone saleApplePhone = new SaleApplePhone();
saleApplePhone.sale("Apple", 1888.00);
SaleHuaWeiPhone saleHuaWeiPhone = new SaleHuaWeiPhone();
saleHuaWeiPhone.sale("HuaWei", 1889.00);
}
如果这样修改来之后,那之后不管哪个手机 做那个活动,或者不做活动,在业务需求扩展的时候都不会相互影响。
这个就是类单一职责,一个类只负责一个功能模块。
有可能在写代码的时候也会这样写
public class Sale {
public void saleApplePhone(String phone, Double price){
System.out.println(phone + " 销售价:" + price);
}
public void saleHuaWeiPhone(String phone, Double price){
System.out.println(phone + " 销售价:" + price);
}
}
调用层:
public class DemoSRP {
public static void main(String[] args) {
Sale sale = new Sale();
sale.saleApplePhone("Apple 6S", 1888.00);
sale.saleHuaWeiPhone("HuaWei Pro ", 1889.00);
}
}
都写在一个类里,但是通过两个不同的方法来区分开不同的职责。
这样也是可以的。在需求扩展,比较复杂的时候,整个类会很长,代码的可读性也就降低了。
这个就是方法单一职责。但是在项目开发过程,对进度、开发人员技术水平很难保证到类上的单一。
在编写过程进来保证接口和方法的单一就好。
虽然可能会看到有公共代码,一般是都提倡,有公共代码,要进行抽取封装。
该抽取封装就要抽取封装,不改抽取封装就不要抽取封装了。
整个处理逻辑还是分开好不抽取就不抽取,各自负责各自职能。
但是在最后,需要记录日志,那就可以吧写日志整个动作,抽取出来一个公共方法调用即可。
现在需求增加,会员制,每个手机会员价不一样。同样在折扣优惠券 对于会员非会员又是不一样的。
那对于整个会员体制的控制,至少要两个职责。我们可以把这个两个职责分开来,都实现一个抽象依赖。
如果在正常设计,肯定会设计一个顶层的接口 例如
public interface ISale {
// 会员价
Double vipPrice();
// 非会员价
Double nonVipPrice();
// 会员免费退货
void freeAdmissionReturnGoods();
// 非会员退货收取3元取件费
void threeRMBReturnGoods();
// ...等等一些会员非会员的差别
}
把这个接口拆开,拆成两个接口 ISaleVip 和 ISaleNonVip
public interface ISaleVip {
// 会员价
Double vipPrice();
// 会员免费退货
void freeAdmissionReturnGoods();
}
public interface ISaleNonVip {
// 非会员价
Double nonVipPrice();
// 非会员退货收取3元取件费
void threeRMBReturnGoods();
}
这样你那个手机会员非会员的实现类就可以继承不同的会员非会员接口。
会员也有级别,也可根据级别在进行一些细节实现,接口接口直接继承。
最终类图
这样改了代码之后,对项目后期维护会方便很多。