单一职责原则 SRP
就一个类而言,仅有一个引起它变化的原因
开闭原则 OCP
通过扩展的方式来实现变化,而不是修改已有代码来实现,尽量不要通过继承等方式添加新的实现
里氏替换原则 LSP
只要父类能出现的地方子类就可以出现,主要体现在实现和继承
依赖倒置原则 DIP
一种特定的解耦形式,高层模块不依赖低层模块,高层模块不依赖细节而是依赖抽象
接口隔离原则 ISP
让客户端依赖的接口尽可能的少。接口拆分,单接口
迪米特原则 LDP
最少知道原则,一个对象对其他对象有最少的了解
实战应用
设计一个网络请求框架,功能包括:网络请求、缓存、返回数据解析等。
1.第一阶段:
所有功能都写在Activity里
问题:没有任何设计可言,当多处调用的时候重复代码太多,修改的话所有地方都需要修改第二阶段
2.第二阶段:
将请求封装到工具类HttpUtils中
问题:HttpUtils类过于臃肿,做的事情过多,请求、缓存等都耦合在这个类中,还有返回数据解析处理只能由外部调用者处理等
3.第三阶段:
- 将缓存功能提取到SpHttpCache中(目前缓存只缓存到sp) (单一职责原则)
- 创建HttpCallBack接口,直接操作请求成功失败的回调,返回结果公共事件的处理放到HttpUtils请求中,如数据解析,不同格式返回数据的兼容
问题:只是把一些公共逻辑封装成了工具类,没有扩展性可言,请求代码全部挤到一堆,调用参数太多,构造方法中可能需要传入十几个参数,如请求方式、请求参数、超时重连、超时时间、是否支持cookie等。如果还需要扩展参数,就需要添加更多的构造方法
4.第四阶段:
- HttpUtils中将参数修改为链式调用,调用者需要的参数就调用,不需要就不调用
public static HttpUtils with(Context context){ return new HttpUtils(context); } private HttpUtils(Context context) { mHttpRequest = new OKHttpRequest(); mParams = new HashMap<>(); this.mContext = context; } public HttpUtils get(){ mType = TYPE_GET; return this; } public HttpUtils param(String key,Object value){ mParams.put(key,value); return this; } public HttpUtils url(String url){ this.mUrl = url; return this; } public <T> void request(final HttpCallBack<T> callback){ // 在此做一些异常判断,如url校验等 mHttpRequest.get(mContext,mUrl,mParams,callback,true); }
- 在请求之前做传参校验
- 将请求封装到OKHttpRequest类中(单一职责原则)
问题:如果想用其他的网络请求,只能修改HttpUtils的调用了,或者可以随时切换网络请求,如何处理
5.第五阶段:
- 创建IHttpRequest接口,在接口中定义get、post等方法
- OKHttpRequest请求类实现IHttpRequest接口接口
- 在HttpUtils中增加一个IHttpRequest参数,调用者可通过链式调用传入实现了IHttpRequest接口的子类
private IHttpRequest mHttpRequest; …… public HttpUtils httpRequest(IHttpRequest httpRequest){ mHttpRequest = httpRequest; return this; } // 可在application设置默认请求 public static void initHttpRequest(IHttpRequest httpRequest) { mInitHttpRequest = httpRequest; } public <T> void request(final HttpCallBack<T> callback){ if(mHttpRequest == null){ mHttpRequest = mInitHttpRequest; } // 异常判断 mHttpRequest.get(mContext,mUrl,mParams,callback,true); }
4. 如果想增加新的网络请求,只需要创建一个实现IHttpRequest的类即可,在调用的时候调用httpRequest()方法将需要的网络请求设置进去
开闭原则:在需要新增网络请求时,不需要修改HttpUtils的代码,只需要新增类,对扩展开放,对修改关闭
里氏替换原则:父类IHttpRequest出现的地方,子类OKHttpRequest就可以出现,HttpUtils.initHttpRequest(new OKHttpRequest());
依赖倒置原则:高层HttpUtils不依赖底层细节(OKHttpRequest),而是依赖底层抽象(IHttpRequest)
迪米特原则:在MainActivity中,使用HttpUtils进行网络请求,不必关系里面是怎么实现的,只知道需要传什么参数,拿到返回最终结果,其他的不关心
5.缓存类也是如此,内存缓存,磁盘缓存(数据库、硬盘)
常用接口可以缓存到内存中和磁盘中,不常用接口可以直接缓存到磁盘中