第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > java solid设计原则_设计模式之SOLID原则

java solid设计原则_设计模式之SOLID原则

时间:2022-10-02 12:30:20

相关推荐

java solid设计原则_设计模式之SOLID原则

什么是SOLID原则

SOLID = SRP(职责单一原则) + OCP(对扩展开发,修改关闭原则)+ LSP(里氏替换原则)+ ISP(接口隔离原则)+ DIP(依赖反转原则)

SRP: Single Responsibility Principle,一个类或者模块只负责完成一个职责;

OCP:Open Closed Principle,软件实体(模块、类、方法等)应该“对扩展开发,对修改关闭”;

LSP:Liskov Substitution Principle,子对象能够替换程序中父类对象出现的任何地方,并且保证原来的程序逻辑行为不变及正确性不被破坏;

ISP: Interface Segregation Principle,客户端应该不强迫依赖它不需要的接口;

DIP:Dependency Inversion Principle,高层模块不要依赖底层模块,高层模块和底层模块之间应该通过抽象来相互依赖,除此之外,抽象不要依赖具体的实现细节,具体实现细节依赖抽象。

SOLID原则评判标准

SRP(职责单一原则)

评判标准

一个类或者模块只负责完成一个职责,不要设计大而全的类,要设计的粒度小、功能单一的类,也就是说一个类包含两个或者两个以上业务不相关的功能,就可以说它的职责不够单一。

类中的代码行数、函数或属性过多,影响代码的可读性和维护性,就需要考虑对类进行拆分;

类依赖其它类过多,或者依赖的类的其它类过多,不符合高内聚、低耦合的设计思想,就需要考虑对类就行拆分;

私有方法过多,考虑能否将私发方法到新的类中,设置为public方法,供更多的类使用,提高代码的复用性;

比较难给定一个适合的名字,很难用一个业务名词概括,说明职责定义的不够清晰;

类中大量的方法都是集中在操作类的几个属性,其它的属性就可以拆分出来。

代码示例

public classUser{

private String id;

private String userName;

private String pwd;

private String phone;

private String city;

private String province;

private String town;

private BigDecimal balance;

publicintaddUser(User user){

return 1;

}

publicintdeleteUser(String id){

return 1;

}

publicListqueryUserByRoleId(String id){

return new ArrayList<>();

}

}

User类对用户基本信息操作比较频繁,但是地址相关信息只在订单相关功能才用到city、province、town可以单独拆分成一个实体;

User基本操作基本不用到账号余额,放到这里有些多余;

addUser和deleteUser在一定场景下符合职责单一原则,但是业务扩展可能需要对删除做权限控制,就不太符合这个原则,没有一定的准则;

queryUserByRoleId虽然查询的是用户相关信息,但引用了其它实体的内容,我们可以认为是职责不单一。

OCP(对扩展开发,修改关闭原则)

评判标准

一段代码是否易于扩展,某段代码在应未来需求变化的时候,能够做到“对外开放,对修改关闭”,那就说明这段代码的扩展性比较好。

添加一个新功能,不可能任何模块、类、方法不做修改。类需要创建、组装、并且做一些初始化操作,才能构建可运行的程序,修改这部分代码是再所难免的。我们要做的经量修改的时间操作更集中、更少、更上层、经量让最核心、最复杂的那部分逻辑代码满足开闭原则。

代码示例

public classOcp{

publicboolean pkgValidate(String userName, String phone){

if(StringUtils.isEmpty(userName)){

return false;

}

if(phone.length() == 1){

return false;

}

return true;

}

}

如果我们需要新增一个报文校验,就会对这个接口的代码做修改,对应的单元测试全部需要改;

这块属于校验的核心功能,每次改还要把之前的功能测试一遍;

示例代码重构

public classOcpUser{

private String id;

private String userName;

private String pwd;

private String phone;

private BigDecimal balance;

//get set方法省略

}

-------------------------------------------------------------

public abstract classOcpHandler{

publicabstractbooleancheck(OcpUser ocpUser);

}

-------------------------------------------------------------

public classPhoneOcpHandlerextendsOcpHandler{

@Override

publicbooleancheck(OcpUser ocpUser){

if(ocpUser.getPhone().length() == 1){

return false;

}

return true;

}

}

-------------------------------------------------------------

public classUserNameOcpHandlerextendsOcpHandler{

@Override

publicbooleancheck(OcpUser ocpUser){

if(StringUtils.isEmpty(ocpUser.getUserName())){

return false;

}

return true;

}

}

-------------------------------------------------------------

public classOcpC{

private List ocpHandlers = new ArrayList<>();

publicvoidaddAlertHandler(OcpHandler ocpHandler){ this.ocpHandlers.add(ocpHandler); }

publicvoidcheck(OcpUser ocpUser){

for (OcpHandler handler : ocpHandlers) {

handler.check(ocpUser);

}

}

}

-------------------------------------------------------------

public classApplicationContext{

private OcpC ocpC;

// 饿汉式单例

private static final ApplicationContext instance = new ApplicationContext();

privateApplicationContext(){

instance.initializeBeans();

}

publicstaticApplicationContextgetInstance(){

return instance;

}

publicvoidinitializeBeans(){

ocpC.addAlertHandler(new PhoneOcpHandler());

ocpC.addAlertHandler(new UserNameOcpHandler());

}

publicOcpCgetOcpC(){

return ocpC;

}

}

-------------------------------------------------------------

public classDemo{

publicstaticvoidmain(String [] args){

OcpUser ocpUser = new OcpUser();

ocpUser.setUserName("张三");

ocpUser.setPhone("13288888888");

ApplicationContext.getInstance().getOcpC().check(ocpUser);

}

}

现在扩展需要改OcpUser新增一个属性,需要校验的属性;

添加一个handler实现check;

在初始化initializeBeans新增一个handler;

在调用的时候加入对应的属性。

我们不能做到完全的对内扩展开放、对修改关闭,我们只可能在最上面抽象尽可能不该动原逻辑的前提下做扩展。

LSP(里氏替换原则)

评判标准

里式替换原则和多态类似,但是多态是实现方式,是面向对象的一个特性,是一种编程语言的语法,原则是规范,规范你怎么开发。

子类违背父类声明要实现的功能,比如说我父类从小到大排序,子类重新这个方法后是从大到小的顺序排序;

子类违背父类对出入、输出、异常约定,入参和出参类型一样,抛的异常类型也必须完全一样;

子类违背父类注释中所罗列的任何特殊说明,实现方法很父类注释方式说明不符。

代码示例

public classParent{

publicvoidsort(List list){

//重小到大排序逻辑

}

publicvoidquery(String userName)throwsNullPointerException{

//查询逻辑

}

/**

* 加1操作

*@paramnum

*/

publicvoidadd(intnum){

num++;

}

}

public classLspextendsParent{

@Override

publicvoidsort(List list){

//重大道小排序逻辑

}

@Override

publicvoidquery(String userName)throwsNotBoundException{

//查询逻辑

}

/**

* 加1操作

*@paramnum

*/

@Override

publicvoidadd(intnum){

num--;

}

}

sort排序的逻辑完全很父类相反;

抛出异常类型不一致;

和注解标识做不相关操作;

ISP(接口隔离原则)

评判标准

接口可以理解成三类,一组API接口集合(业务具体功能点)、单个API接口或者函数(类中的某一个方法)、OOP中的接口(Inteface)概念。

设计职责更加单一的接口,单一就意味着通用、复用性好;

某些类在实现接口的时候,需要重写一些不需要的方法,做了一些无用功。

代码示例

public interfaceCommonService{

publicListqueryUserName(String status);

publicintdeleteUser(Long id);

publicListqueryRoleName(String userName);

publicintdeleteRole(Long id);

}

public classRoleImplimplementsCommonService{

@Override

publicListqueryUserName(String status){

return null;

}

@Override

publicintdeleteUser(Long id){

return 0;

}

@Override

publicListqueryRoleName(String userName){

return null;

}

@Override

publicintdeleteRole(Long id){

return 0;

}

}

public classUserImplimplementsCommonService{

@Override

publicListqueryUserName(String status){

return null;

}

@Override

publicintdeleteUser(Long id){

return 0;

}

@Override

publicListqueryRoleName(String userName){

return null;

}

@Override

publicintdeleteRole(Long id){

return 0;

}

}

接口不灵活,用户和角色的接口放在一起要多做一个工作量

复用性很差

不利于代码拆分、管理

DIP(依赖反转原则)

评判标准

依赖反转原则也可以叫依赖倒置原则,高优先级的类不应该强行依赖低优先级的类,而是通过一个抽象类间接的操作,子类也基于抽象类做实现。

代码是否易于拆分,在代码重构的时候很难对模块之间解耦,就说明依赖关系太死;

低层次模块提供的接口要足够的抽象、通用,在设计时需要考虑高层次模块的使用种类和场景;

高层次模块没有依赖低层次模块的具体实现,方便低层次模块的替换。

代码示例

interfaceIWorker{

publicvoidwork();

}

classWorkerimplementsIWorker{

publicvoidwork(){

// ... working

}

}

classSuperWorkerimplementsIWorker{

publicvoidwork(){

// ... working much more

}

}

classManager{

IWorker worker;

publicvoidsetWorker(IWorker w){

this.worker = w;

}

publicvoidmanage(){

this.worker.work();

}

}

Manager具体实现不依赖Worker和SuperWorker类;

通过抽象接口IWorker相互依赖;

具体实现类依赖接口IWorker;

个人网站:/

公众号:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。