关闭

通过在Android实际开发初探模板模式(一)

标签: 实际开发Android模板模式
3686人阅读 评论(12) 收藏 举报
分类:

最近比较忙,就很少更新自己的笔记(blog),昨天一个功能的开发中,总觉得那个页面会是一个很好的案例,就想把它记录到笔记中,今天忙中偷闲,把它单独拿出来做个笔记分享下。首先,我们先看下效果图:
这里写图片描述
看到这个的时候,当时瞬间有点兴奋,解决方案爆棚

  1. 在一个activity中用五个listview或者recyclerview控制显示和隐藏
  2. 在一个activity中用一个listview或者recyclerview
  3. tablayout+viewpager+fragment
  4. ………………
  5. ………………
    或许还有更多比较好的解决方案,当我想到第三种方案的时候我就停下来了,决定选用第三种方案,如果选用第一种方案,五个控件控制显隐也是很繁琐很啰嗦的事情,总觉得有点奇葩,第二种方案,每次点击就要重新获取数据,会产生资源浪费,没必要每次都去数据请求,选择第三种方案,通过viewpager设置缓存页面数,只需要一次请求,然后不断切换fragment就可以实现以上效果,何乐而不为呢?
    选择的解决方案先分析到这里,接下来便是功能实现的过程,实现功能的时候没做太多的考虑,首先写了一个AllOrderFragment.java,把全部订单的功能先实现了,但我看了下接口的时候,瞬间觉得自己太冲动了,除了接口中需要传入的“st”参数以外,其它参数都相同,请求的接口名称也相同,返回的json格式和字段名称也是一样的,我勒个擦,如果使用AllOrderFragment.java的方式,不断拷贝粘贴,功能上是ok的,但是重复造了五次轮子,确实有点坑爹,代码的冗余不需多说,赤裸裸的展示在我眼前。
    想起了一句话,“很多事情的改变就因为一句我受够了”,是的,我受够了,前三年重复造的轮子太多,造成好多时候维护起来很麻烦,开发的过程中,不需要刻意去强加某种模式,当我们发现同样或者类似的代码写了两次或者两次以上的时候,就要想着去封装,或者用某种更好的方式去提高代码的可重用性,此刻,我决定把AllOrderFragment.java里面代码进行提取,如下:
/**
 * 
 * created by zero on 2016-06-21
 *
 * 我的订单中,五个fragment的父类
 */
public abstract class BaseOrderFragment extends BaseFragment<MyOrderPresenter> implements IMyOrder
{
    private RecyclerView rv_order;
    private LinearLayout ll_no_order;

    private int page_count;
    private int load_count;
    private int indexPager;

    private List<MyOrderModel> model;
    private LinearLayoutManager layoutManager;
    private MyOrderAdapter adapter;
    private RecyclerViewListener listener;

    @Override
    protected int initLayout() {
        // TODO Auto-generated method stub
        return R.layout.fragment_order_view;
    }

    @Override
    protected void initData(View rootView) {
        //从源码中剥离,此处未使用注解view
        rv_order = (RecyclerView) rootView.findViewById(R.id.rv_order);
        ll_no_order = (LinearLayout) rootView.findViewById(R.id.ll_no_order);
        layoutManager = new LinearLayoutManager(getMyActivity());
        layoutManager.setOrientation(LinearLayout.VERTICAL);
        rv_order.setLayoutManager(layoutManager);
        //子类通过requestParams()把st中不同的字段传过来
        fragmentPresenter.requestOrder(requestParams());
    }

    //与子类沟通的关键之处
    abstract protected String requestParams();

    //以下三个方法是BaseFragment中的方法,既然是实际开发,就有点实际开发的样子,这部分代码未删去
    @Override
    protected Class<MyOrderPresenter> getPsClass() {
        // TODO Auto-generated method stub
        return MyOrderPresenter.class;
    }

    @Override
    protected Object getIView() {
        // TODO Auto-generated method stub
        return this;
    }

    @Override
    protected void clickView(View v) {
        // TODO Auto-generated method stub

    }

    @Override
    public void sendModel(MyOrderParentModel mModel, RequestParams params) {
        //此处是对model的处理、recyclerview的上拉加载,代码已删
    }

    //以下代码可以无视,实际就是用来更新adapter
    private void adapterNotify() {
        // TODO Auto-generated method stub
        if(adapter!=null){
            if (indexPager > adapter.getItemCount() - 1)
            {
                MyOrderAdapter.isShowFooter = true;
            } else
            {
                MyOrderAdapter.isShowFooter = false;
            }
            adapter.notifyDataSetChanged();
        }
    }
}
/**
 * 
 * created by zero on 2016-06-21
 *
 */
public class OrderListFragment extends BaseOrderFragment
{

    @Override
    protected String requestParams() {
        // TODO Auto-generated method stub
        return "list";
    }
}
public class PendingPayFragment extends BaseOrderFragment
{

    @Override
    protected String requestParams() {
        // TODO Auto-generated method stub
        return "pending";
    }
}

五个子类,此处只列举两个,其它三个代码几乎一样,只需要实现requestParams()就ok,以父类做为模板,一行代码搞定所有问题,昨天写完后,我瞬间笑了,第一次在fragment中写这么少的代码,^_^

/**
 * 
 * created by zero on 2016-06-21
 * 
 * 我的订单presenter
 *
 */
public class MyOrderPresenter extends BasePresenter
{

    private Context context;
    private Handler handler;
    private IMyOrder iView;
    private final static int MY_ORDER_CODE = 0X000012;

    /**
     * 以下@Override的几个方法,都是父类BasePresenter的抽象方法,BasePresenter在此不暴露了
     */
    @Override
    public void initBaseData(Context context, Handler handler, Object iView,
            Intent intent) {
        this.context = context;
        this.handler = handler;
        if(iView instanceof IMyOrder){
            this.iView = (IMyOrder) iView;
        }
    }

    @Override
    public void initData() {
        // TODO Auto-generated method stub

    }

    /**
     * 
     * @param orderType
     * 
     * 五个fragment就因为orderType参数不同
     */
    public void requestOrder(String orderType) {
        params.put("act", getActionName());
        params.put("st", orderType);
        params.put("token", Constants.getInstance().token);
        params.setSuccessMsgWhat(MY_ORDER_CODE);
        HttpTools.request(params, context, handler);
    }

    @Override
    public String getActionName() {
        // TODO Auto-generated method stub
        return URLUtils.MEMBER_ORDER;
    }

    @Override
    public void handMsg(Message msg) {
        // TODO Auto-generated method stub
        switch (msg.what)
        {
        case MY_ORDER_CODE:
            MyOrderParentModel model = JsonToModel.getJsonArrayToModelAndPage(
                    msg, MyOrderParentModel.class);
            if(iView!=null&&model!=null){
                iView.sendModel(model,params);
            }
            break;

        default:
            break;
        }
    }
}

以上提到的几个model和interface就不发出来了,根据自己的需要去写,这些没有任何曝光价值,以下是项目中运行的结果:
zero

接下来,我们再从理论上分析模板方法模式,模板模式指的是定义一个操作中算法的轮廓和骨架,而将一些步骤延迟放到子类里,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

BaseOrderFragment (Abstract Template)
1、是抽象类,其实就是一个抽象模板,定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。说白了,就是一个父类让子类继承,把一些相似的操作和步骤放在父类,提高代码的重用性。

2、定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。说白了,其实就是父类中抽象出一个方法,让每个子类都去重写这个方法,在上述代码中,子类重写的那部分,即requestParams()。

OrderListFragment、PendingPayFragment (Concrete Template)
实现父类所定义的一个或多个抽象方法,每个父类可以有多个子类与之对应,每个子类可以给出这些抽象方法不同的实现,从而使得顶级逻辑的实现各不相同,说白了,就是上述实现过程中,因为传的st各不相同,返回的json数据内容之间的不同,最终导致每个fragment页面的展示也不同。

UML如下:
UML

总结:这次运用模板模式完全属于意外,在这之前,我对模板模式了解并不多,只是写完后,觉得和模板模式的思想挺符合的,昨晚把《大话设计模式》中的模板模式章节读了一遍,确实运用的就是模板模式。在这之前,一个好朋友问我,在实际开发中,运用到哪些设计模式,我和他说,代码能力有限,用到的很少,其实,我们并不需要刻意去把某个功能套上设计模式,强加的设计模式,并不会让代码写的优雅,反而觉得不伦不类,只有实际开发中运用到了,也确实需要这种模式,当你写完的时候,也许你也会会心一笑。

1
2
查看评论

Android 设计模式之模板模式

模板定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • alitter
  • alitter
  • 2014-08-27 14:37
  • 336

模板方法模式例子

原文地址:http://www.cnblogs.com/jenkinschan/p/5768760.html一、概述 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。二、结构类图三、解决问题模板方法就是提供...
  • disiwei1012
  • disiwei1012
  • 2016-12-05 17:14
  • 897

Android设计模式系列--模板方法模式

Android设计模式系列--模板方法模式 模板方法,和单例模式是我认为GOF的23中最简单的两种模式。 但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分,是面向对象的一种基本...
  • wwj_748
  • wwj_748
  • 2013-11-29 11:48
  • 2013

Sipdroid源码初探(二):监听来电,通话建立流程

sipdroid的通话建立过程
  • qq_15650553
  • qq_15650553
  • 2016-02-16 09:23
  • 765

关于java并发,实际开发中的体会

1:java并发的分类,在实际开发中我一般讲java并发分为2个大类 1)业务并发,也叫程序并发,比如同时打开两个相同的网页.然后同时点了2个相同的按钮.(也就是java中的多线程) 2)数据并发,数据库中某个表中的某条记录,被多个程序同时使用.其中给一个程序对数据进行了修改,会影响另外一个程序...
  • u010523770
  • u010523770
  • 2016-10-10 11:38
  • 920

Android中的模板方法模式

定义:定义一个方法操作算法的框架(骨架结构),而将一些步骤延迟到子类中。模板方法使子类可以在不改变一个算法的结构的情况下,就可以重定义该算法的某些特定步骤。就像一个工厂车间的流水线一样,每一步其实都是可以固定的,就是具体的内容有些区别,这样就可以定义一个大致的流程框架,子类就直接按照这个框架来就可以...
  • hp910315
  • hp910315
  • 2016-03-12 21:43
  • 978

Android源码分析之模板方法模式

Android源码分析之模板方法模式,Android中AsyncTask的模板方法设计模式
  • bboyfeiyu
  • bboyfeiyu
  • 2014-08-14 18:19
  • 3674

java中的多态在实际开发中的作用

①可以增强代码的健壮性。只管按照父类的设计进行操作,不管具体是什么样的子类,将来这个子类用着不舒服了,换一个就行,不影响原来的代码,这样代码维护起来更加容易。 示例代码: class Car { void run () {} } class BMW extends Car{} c...
  • Routine_limon
  • Routine_limon
  • 2018-01-04 18:15
  • 176

Android开发之模板模式初探

模板模式我觉得在Android的开发中是最长用到的,基本是随处可见的,认识该模式,有助于我们对Android的源码及框架有一个更深层次的认识。那什么是模板模式呢,模板模式就是定义一个基本框架,将其中的一些方法延迟到子类中执行实现。就比如我们去餐馆吃饭,基本步骤肯定为找到座位,点菜,上菜,吃饭,买单五...
  • u013900875
  • u013900875
  • 2014-08-11 15:33
  • 1207

C++11 并发指南系列(C++11 多线程初探)

C++11 并发指南一(C++11 多线程初探) 引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧,和大家共勉。 相信 Linux 程序员都用...
  • chenjh213
  • chenjh213
  • 2014-12-27 18:45
  • 609
    个人资料
    • 访问:264020次
    • 积分:2999
    • 等级:
    • 排名:第13879名
    • 原创:46篇
    • 转载:0篇
    • 译文:0篇
    • 评论:329条
    QQ交流群

    Android路上

    611566797
    博客专栏
    我的公众号