漫谈设计模式之:策略模式--实现无缝切换模块功能(网络、日志、图片等)

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情

简介

我们知道,android每一种模块都有很多种解决方案,比如网络模块有OKHttp,Volley,Retrofit等;数据库有OrmLite,GreenDao,Room等;图片模块有Glide,Picaso等。
平时我们开发的时时候可能就会选定一种模块,比如图片我们就用Glide,然后在项目的代码里面直接调用Glide的接口完成图片处理功能。
其实粗略一看到也没什么问题,如果我们不更换这些模块的话。
但是,万一哪一天有了一个更好的解决方案呢?或者,公司开发了一个中间件,也是用来解决这个模块的问题,然后公司通知需要各个项目都接入这个模块
这种情况下,我们通常的解决方案是: 将项目中所有用到原先模块API的地方,统统换成新引入模块的API,这样不仅工程量大,而且还容易造成改出新的问题;而且新的模块的API也需要重新了解熟悉。

解决方案

根据设计模式中的“开闭原则”,我们尽量应该做到对修改关闭。
想上述提到的解决方案,相当于是业务跟模块之间强耦合了。
那么怎么解决这种“强耦合”呢?接口
我们在使用模块功能的时候,尽量不要直接使用模块提供的API接口,而是使用我们定义的接口提供的方法,也就是我们通常说的面向接口编程。
具体的解决方案:

  1. 定义一个接口,这个接口的方法就是我们项目里面说调用的;
  2. 所引用的模块都要实现这个接口,虽然模块本身有自己的API,但是我们现在不是直接使用模块的API,而是使用我们定义的接口。所以这个模块必须要实现我们定义的接口;
  3. 提供一个使用类,通常是单例模式。这个使用类就是我们项目里面所直接调用的,所以这个使用类也必须实现我们定义的接口。
  4. 在使用类中指定所引用的第三方模块。比如Glide或者Picaso,或者是公司机制提供的中间件模块。
    这种解决方案的好处就是,无论怎么替换第三方模块,项目使用到这个模块功能的地方都不需要改动,只需要在配置里面设定好使用的第三方模块即可。

实例代码

public interface ILogProcessor {
    void v(String vLog);

    void d(String dLog);

    void i(String iLog);

    void e(String eLog);
}
private static volatile LogLoader sInstance = null;
    private static ILogProcessor sILogProcessor;
    private LogLoader() {

    }
    public static LogLoader getInstance () {
        if (sInstance == null) {
            synchronized(LogLoader.class){
                if (sInstance == null) {
                    sInstance = new LogLoader();
                }
            }
        }
        return sInstance;
    }

    public static ILogProcessor load(ILogProcessor logProcessor) {
        return sILogProcessor = logProcessor;
    }

    @Override
    public void v(String vLog) {
        sILogProcessor.v(vLog);
    }

    @Override
    public void d(String dLog) {
        sILogProcessor.d(dLog);
    }

    @Override
    public void i(String iLog) {
        sILogProcessor.i(iLog);
    }

    @Override
    public void e(String eLog) {
        sILogProcessor.e(eLog);
    }
}
public class DefaultLogProcessor implements ILogProcessor {
    @Override
    public void v(String vLog) {
        Log.v("DefaultLogProcessor", "defaultlog:" + vLog);
    }

    @Override
    public void d(String dLog) {
        Log.d("DefaultLogProcessor", "defaultlog:" + dLog);
    }

    @Override
    public void i(String iLog) {
        Log.i("DefaultLogProcessor", "defaultlog:" + iLog);
    }

    @Override
    public void e(String eLog) {
        Log.e("DefaultLogProcessor", "defaultlog:" + eLog);
    }
}
public class TinyLogProcessor implements ILogProcessor {
    @Override
    public void v(String vLog) {
        TinyLog.v("tinylog:" + vLog);
    }

    @Override
    public void d(String dLog) {
        TinyLog.d("tinylog:" + dLog);
    }

    @Override
    public void i(String iLog) {
        TinyLog.i("tinylog:" + iLog);
    }

    @Override
    public void e(String eLog) {
        TinyLog.e("tinylog:" + eLog);
    }
}
public class LogLoader implements ILogProcessor{

    private static volatile LogLoader sInstance = null;
    private static ILogProcessor sILogProcessor;
    private LogLoader() {

    }
    public static LogLoader getInstance () {
        if (sInstance == null) {
            synchronized(LogLoader.class){
                if (sInstance == null) {
                    sInstance = new LogLoader();
                }
            }
        }
        return sInstance;
    }

    public static ILogProcessor load(ILogProcessor logProcessor) {
        return sILogProcessor = logProcessor;
    }

    @Override
    public void v(String vLog) {
        sILogProcessor.v(vLog);
    }

    @Override
    public void d(String dLog) {
        sILogProcessor.d(dLog);
    }

    @Override
    public void i(String iLog) {
        sILogProcessor.i(iLog);
    }

    @Override
    public void e(String eLog) {
        sILogProcessor.e(eLog);
    }
}
public class SwitcherFragment extends BaseFragment {
    @Override
    protected void initViewsAndEvents(Bundle savedInstanceState) {

    }

    @Override
    protected int getContentViewLayoutID() {
        return R.layout.fragment_solution_switcher;
    }

    @OnClick({R.id.btn_log1, R.id.btn_log2})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_log1:
                LogLoader.load(new TinyLogProcessor());
                LogLoader.getInstance().d("this is tiny log");
                break;
            case R.id.btn_log2:
                LogLoader.load(new TinyLogProcessor());
                LogLoader.getInstance().d("this is system default log");
                break;
        }
    }
}

git地址

https://github.com/ddnosh/AndroidQuick

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值