码迷,mamicode.com
首页 > 其他好文 > 详细

用装饰模式优化的一个实例2

时间:2017-08-25 21:02:50      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:ada   关系   有一个   两种   complete   creat   loader   model   coder   

业务场景

写一个数据层的loader,loader的数据拉取有可能走本地或者走网络,所以肯定需要通过回调来返回数据,而且两种情况在view层的表现不一样,也需要通过回调来告知

优化前

于是我一开始设计了这么两个接口来进行区分处理,而对于每个接口,都像网络请求一样写了4个回调,以适应任何意外情况

public interface ShortLoadAction<T> {
    void onStartShort();

    void onCancelShort();

    void onBrokenShort();

    void onCompleteShort(int stateCode, String stateMsg, T model);
}

public interface LongLoadAction<T> {
    void onStartLong();

    void onCancelLong();

    void onBrokenLong();

    void onCompleteLong(int stateCode, String stateMsg, T model);
}

你会发现这两个接口方法类似,但名字不一样,因为我接下来写一个业务封装适配器类,为view层做了一个翻译,这个类需要实现上面两个接口,所以如果方法名一样就不行,就像这样,虽然这样有点怪,但好像没有办法

public abstract class LoadAction<T> implements ShortLoadAction<T>, LongLoadAction<T> {

    @Override
    public void onStartShort() {
        // do nothing
    }

    @Override
    public void onCancelShort() {
        onFailed();
    }

    @Override
    public void onBrokenShort() {
        onFailed();
    }

    @Override
    public void onCompleteShort(int stateCode, String stateMsg, T model) {
        onSuccess(model);
    }

    /*-------------------------------------------------*/

    @Override
    public void onStartLong() {
        showLoadingView();
    }

    @Override
    public void onCancelLong() {
        hideLoadingView();
        onFailed();
    }

    @Override
    public void onBrokenLong() {
        hideLoadingView();
        onFailed();
    }

    @Override
    public void onCompleteLong(int stateCode, String stateMsg, T model) {
        hideLoadingView();
        onSuccess(model);
    }

    /*--------------------------------------------------------------------------------------------*/

    public abstract void showLoadingView();

    public abstract void hideLoadingView();

    public abstract void onFailed();

    public abstract void onSuccess(T model);
}

有了这个抽象类,使用者可以知道得更少了,只管实现LoadingView的显示隐藏、处理成功失败就行了,耗时长短这个信息不需要去关心。

为了进一步方便使用,利用我的ViewHelp写了一个用起来更简单的adapter:

public abstract class VHelperLoadAction<T> extends LoadAction<T> {
    private ViewHelper viewHelper;

    public VHelperLoadAction(ViewHelper viewHelper) {
        this.viewHelper = viewHelper;
    }

    @Override
    public void showLoadingView() {
        viewHelper.showLoadingView();
    }

    @Override
    public void hideLoadingView() {
        viewHelper.hideLoadingView();
    }
}

这下使用者只需要关心成功失败了

写完一用感觉很不错,完全没有感觉不对或者是不符合设计模式什么的,ShortLoadActionLongLoadAction方法名的奇怪感觉早就忘得一干二净。
比如这样:

VHelperLoadAction<List<WordPage>> loadAction = new VHelperLoadAction<List<WordPage>>(vHelper) {
    @Override
    public void onFailed() {
        vHelper.toastNetworkBroken();
    }

    @Override
    public void onSuccess(List<WordPage> model) {
        CheckWordsActivity.start(getActivity(), model);
    }
};

pageWordsLoader.load(pages, loadAction, loadAction);

这个loader长这样

public void load(List<String> pageIds, ShortLoadAction<List<WordPage>> loadShortAction, LongLoadAction<List<WordPage>> loadLongAction) {
    this.pageIds = pageIds;
    dbHelper.createTableIfNotExist();

    List<String> unsavedPageNumbers = getUnSavedPageNumbers();
    if (unsavedPageNumbers.isEmpty()) {
        loadWordsFromLocal(loadShortAction, null);
    } else {
        loadWordsFromRemote(unsavedPageNumbers, loadLongAction);
    }
}

优化中

这个代码还给别人讲过,讲完两人也都没觉得有问题。直到一次codereview中,我刚跟老大解释完这几个action的关系,老大就表示这个设计有点问题。

开始他是觉得后边这个load()方法中需要传两个action进去非常奇怪,但我知道这块是必须这样的,因为loader的使用者是不知道也不应该关心到底选择哪种actionloader应该自己去看本地有没有数据,然后选择short或者long的action。大家都同意这个观点。
(但还有一个同事认为两个action还是不应该,你其实可以只写一个action,然后每个回调方法有一个参数:isLong,回调方法中就可以根据不同的参数来做不同的事,我只能说这是最差的设计了,)
然后我们老大就指出了这部分代码的最大问题,在于ShortLoadActionLongLoadAction俩个明显有相似关系的东西居然没有一点关系,是两个完全不同的接口,同时,在loader的最里层(关心选择short或者long的action的里层),本来可以不关心具体是short还是long的action,现在直接关心了(持有对象类型是具体的ShortLoadAction或LongLoadAction)。
这个问题可以用继承来,但是相比之下,使用装饰模式更加合适,装饰模式不仅有使用继承的全部好处,而且还有更多好处。
然后最后你会发现,你虽然写不出来一个跟之前VHelperLoadActionLoadAction一样的东西,但使用新的装饰器写法时也是一样方便好用

优化后2

技术分享?


但其实后来发现我们的适配设备(是个专门给某个pad开发并且烧录进去一块卖钱的软件)性能实在捉急,以至于在本地取数据花的时间也不短,所以需要跟网络请求一样显示加载圈,于是最后我只用了一个WaitLoadAction(摊手)

用装饰模式优化的一个实例2

标签:ada   关系   有一个   两种   complete   creat   loader   model   coder   

原文地址:http://www.cnblogs.com/bellkosmos/p/yong-zhuang-shi-mo-shi-you-hua-de-yi-ge-shi.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!