设计模式之面向对象的六大基本原则(含具体事例)

写完代码过后需求更改你需要改很多个地方的代码,证明你的代码是有问题的。

simple1

简单的在Activity中访问网络然后解析数据,这种方式是我们大家刚开始接触代码时写出来的。

 protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
       Map<String, Object> params = new HashMap<>();
       params.put("iid", 201321092107L);
       params.put("password", "woshihaizeiwang");
       final Request request = new Request.Builder().url("www.cailei.com").build();
       Call call = okHttpClient.newCall(request);
       call.enqueue(new Callback() {
           @Override
           public void onFailure(Call call, IOException e) {
               //数据失败
           }

           @Override
           public void onResponse(Call call, Response response) throws IOException {
               Log.e("response", response.body() + "");
               final String resultJson = response.body().string();
               //1.Json数据解析 2.显示列表数据 3.缓存数据

           }
       });

simple2

第二步,将一些公共方法封装成工具类,每一次调用网络访问的时候就调用HttpUtils的静态方法;

public class HttpUtils {
    public HttpUtils(){

    }
    public static void get(Context context, String baseUrl, Map<String,Object> params, final Callback callback){
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        //公共参数
        params.put("iid", 201321092107L);
        params.put("password", "woshihaizeiwang");
        final Request request = new Request.Builder().url(baseUrl).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //数据失败
                callback.onFailure(call,e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//                Log.e("response", response.body() + "");
//                final String resultJson = response.body().string();
                //1.Json数据解析 2.显示列表数据 3.缓存数据
                callback.onResponse(call,response);
            }
        });
    }

simple3

可以看见simple2中网络访问没有加入缓存,只是将一些公共的网络逻辑写成了一个工具类,simple3加入了缓存,然后利用反射将okhttp返回的结果处理成了Bean类。

 public static <T> void get(Context context, String baseUrl, Map<String, Object> params, final
    HttpCallBack<T> callBack, final boolean cache) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        //公共参数
        params.put("iid", 201321092107L);
        params.put("password", "woshihaizeiwang");
        String joinUrl = baseUrl + parseParams(params);
        final String cacheJson = (String) SharePreferencesUtils.getInstance().getParam("joinUrl",
                "");
        if (cache && !TextUtils.isEmpty(cacheJson)) {
            Gson gson = new Gson();
            T resultBean = (T) gson.fromJson(cacheJson, getResultBeanClass(callBack));
            callBack.onSuccess(resultBean);
        }
        final Request request = new Request.Builder().url(baseUrl).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //数据失败
                callBack.onFail(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//                Log.e("response", response.body() + "");
                final String resultJson = response.body().string();
                //1.Json数据解析 2.显示列表数据 3.缓存数据
                Gson gson = new Gson();
                T objectJson = (T) getResultBeanClass(callBack);
                callBack.onSuccess(objectJson);
                if (cache) {
                    SharePreferencesUtils.getInstance().saveParam("joinurl", resultJson);
                }
            }
        });
    }

    private static String parseParams(Map<String, Object> params) {
        return "sb";
    }

    public static <T> Class<?> getResultBeanClass(HttpCallBack<T> callBack) {
        Type type = callBack.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) type).getActualTypeArguments();

        return (Class<?>) params[0];
    }

单一职责原则

就一个类而言,应该仅有一个引起它变化的原因。简单来说,一个类中应该是一组相关性很高的函数,数据的封装。
simple3中的请求和缓存全都写到了一堆,根据单一职责的原则我们来更改一下代码:

新建一个类:HttpRequest.java

public class OkhttpRequest {
    private SpHttpCache spHttpCache;

    public OkhttpRequest(){
        spHttpCache=new SpHttpCache();
    }
    public <T> void get(Context context, String baseUrl, Map<String, Object> params, final HttpCallBack<T> callBack, final boolean cache) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        //公共参数
        params.put("iid", 201321092107L);
        params.put("password", "woshihaizeiwang");
        final String joinUrl = baseUrl + parseParams(params);
        final String cacheJson = spHttpCache.getCache(joinUrl);
        if (cache && !TextUtils.isEmpty(cacheJson)) {
            Gson gson = new Gson();
            T resultBean = (T) gson.fromJson(cacheJson, getResultBeanClass(callBack));
            callBack.onSuccess(resultBean);
        }
        final Request request = new Request.Builder().url(baseUrl).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //数据失败
                callBack.onFail(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//                Log.e("response", response.body() + "");
                final String resultJson = response.body().string();
                //1.Json数据解析 2.显示列表数据 3.缓存数据
                Gson gson = new Gson();
                T objectJson = (T) getResultBeanClass(callBack);
                callBack.onSuccess(objectJson);
                if (cache) {
                   spHttpCache.saveCache(joinUrl,resultJson);
                }
            }
        });
    }

    private static String parseParams(Map<String, Object> params) {
        return "sb";
    }

    public static <T> Class<?> getResultBeanClass(HttpCallBack<T> callBack) {
        Type type = callBack.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) type).getActualTypeArguments();

        return (Class<?>) params[0];
    }

可以发现这个类中依赖着另外一个类SpHttpCache.java(这个类的作用就是进行sp缓存):

public class SpHttpCache {
    public void saveCache(String url, String json) {
        SharePreferencesUtils.getInstance().saveParam(url, json);
    }

    public String getCache(String url) {
        return (String) SharePreferencesUtils.getInstance().getObject(url);
    }
}

我们已经把网络请求和缓存都各自封装成类了,保证了单一职责

HttpUtils.java
public class HttpUtils {
    private OkhttpRequest okhttpRequest;
    public HttpUtils() {
        okhttpRequest=new OkhttpRequest();
    }

    public  <T> void get(Context context, String baseUrl, Map<String, Object> params, final HttpCallBack<T> callBack, final boolean cache) {
        okhttpRequest.get(context,baseUrl,params,callBack,true);
    }

我们每次访问网络直接调用HttpUtils的get方法就行了。但是有没有发现如果我们在get方法里面继续加一些参数,这样这get方法就会很长很长,用的人也要去搞清楚这个方法里面的参数到底是干什么的,万一传错了值呢?这时候我们可以采用链式调用的方式改进代码

public class HttpUtils {
    private OkhttpRequest okhttpRequest;
    private final int TYPE_POST = 0x0011, TYPE_GET = 0x0022;
    private String mUrl;
    private Context mContext;
    private Map<String, Object> mParams;

    private HttpUtils(Context context) {
        okhttpRequest = new OkhttpRequest();
        mParams = new HashMap<>();
        this.mContext = context;
    }

    public static HttpUtils with(Context context) {
        return new HttpUtils(context);
    }

    public HttpUtils param(String key, Object value) {
        mParams.put(key, value);
        return this;
    }

    public HttpUtils url(String url) {
        this.mUrl = url;
        return this;
    }

    public HttpUtils cache(boolean cache) {
        // TODO
        return this;
    }

    public <T> void get(final HttpCallBack<T> callback) {
        okhttpRequest.get(mContext, mUrl, mParams, callback, true);
    }

问题,当我们要用xutils,okhttp,Retrofit…的时候怎么切换第三方网络框架?

开闭原则

定义:软件中的对象(类,模块,函数)应该对于扩展是开放的,对于修改是关闭的。
什么意思?比如说上面你要换一个网络框架的时候,你是不是得去吧HttpUtils里面的OkhttpRequest引擎改成其他的比如Xutils的引擎。我们尽量的让用户少一点的知道了解我们的代码,我们对外就开放一个HttPUtils类,用户传一些参数就能访问网络获取数据。在不改变这个类的代码的情况下怎么去更换网络引擎。

   private static IHttpRequest httpRequest;
    private final int TYPE_POST = 0x0011, TYPE_GET = 0x0022;
    private String mUrl;
    private Context mContext;
    private Map<String, Object> mParams;

    private HttpUtils(Context context) {
        okhttpRequest = new OkhttpRequest();
        mParams = new HashMap<>();
        this.mContext = context;
    }

    public static HttpUtils with(Context context) {
        return new HttpUtils(context);
    }

    public HttpUtils param(String key, Object value) {
        mParams.put(key, value);
        return this;
    }

    public HttpUtils url(String url) {
        this.mUrl = url;
        return this;
    }

    public HttpUtils cache(boolean cache) {
        // TODO
        return this;
    }

    public <T> void get(final HttpCallBack<T> callback) {
        httpRequest.get(mContext, mUrl, mParams, callback, true);
    }

    public static void initHttpRequest(XutilsHttpRequest xutilsHttpRequest) {
        this.httpRequest = xutilsHttpRequest;
    }
BaseAplication.java:
public class BaseAplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        HttpUtils.initHttpRequest(new XutilsHttpRequest());
    }
}

里斯替换原则

定义:只要父类能出现的地方子类就可以出现,主要体现就是实现和继承,上面的BaseAplication的initHttpRequest中的接口参数是父类,但是传进去的是实现了接口的子类。

依赖倒置原则

定义:指代了一种特定的解耦方式,高层模块不依赖低层次模块的细节,说白了高层次就是不依赖细节而是依赖抽象。比如HttpUtils中的okhttpRequest就是一个细节,是底层次的。后来的iHttpRequest就是抽象的,所以我们依赖的是iHttpRequest.

接口隔离原则

定义:将接口拆分,类似于单一原则,就是接口里面的功能是一种类型的不能有其他的类型
上面5个原则都跟接口和抽象有关(面向接口和面向抽象)

迪米特原则(最少知识原则)

一个对象应该对其他对象有最少的了解,就像用户调用HttpUtils传一些参数就可以了,不需要了解内部实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜的OnePiece

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值