回调函数设计及应用(Java)——分组模式设计

背景:在项目中因为牵涉到大数据的处理,需要经常在各个类中用到分组的模式。同样地流程控制代码,到处copy,导致一个地方出错,每个地方都需要修改。因此考虑将此模式提取出来。

分析:鉴于分组模式是固定的,分组后需要处理的事务是动态的,让我联想到JavaScript里经常用的回调函数正好如此。因此可以结合Java语言特性借鉴js处理方式,将动态方法体放到回调函数中。

设计:

分组模式基本流程是:  1.根据总数/每组分配个数,得到组数N

                            2.根据总数%每组分配个数,得到余数组组员个数M

                            3.如果总数整除每组分配个数,M值为0,总组数为N,否则总组数为N+1

                            4.进行分组循环

                            5.按每组分配的个数进行组内循环,如果M值不为0,则最后一组组内循环M次

设计:                   1.根据分组模式基本流程可知分组流程需要参数为总数、每组分配个数、组内循环具体需要执行的方法体

                           2.分组模式中产生了内部变量当前循环的组号i、当前循环的组内编号j,总计分成的组数,因此回调函数需要传出这三个参数,提供给动态方法体调用。

                           3.借用java中的方法重载来实现动态方法体,借助接口来实现回调函数的可扩展性。

具体实现:             1.IDealByGroupCallback.java 回调函数接口类

                          2.DealByGroupCallback.java  回调函数接口实现类

                          3.DealByGroup.java             分组流程实现类

                          4.TestDemo.java                 测试调用类

代码:IDealByGroupCallback.java    回调函数接口类

1 public interface IDealByGroupCallback {
2     public void func(int index,int groupIndex,int totalgroup);
3 }

        DealByGroupCallback.java    回调函数接口实现类

1 public class DealByGroupCallback implements IDealByGroupCallback{
2     public DealByGroupCallback() {
3       }
4     public void func(int index,int groupIndex,int totalgroup){
5         System.out.print("index:" + index);
6         System.out.print(" groupIndex:" + groupIndex);
7         System.out.println(" totalgroup:" + totalgroup);
8     }
9 }

        DealByGroup.java    分组流程实现类

 1 public class DealByGroup {
 2       int totalCount;
 3       int perCount;
 4       IDealByGroupCallback dealByGroupCallback;
 5       public DealByGroup(int totalCount, int perCount,IDealByGroupCallback dealByGroupCallback)
 6       {
 7           this.totalCount = totalCount;
 8           this.perCount = perCount;
 9           this.dealByGroupCallback = dealByGroupCallback;
10       }
11       public void deal()
12       {
13         //在这里写分组查询
14         int n = totalCount / perCount;
15         int m = totalCount % perCount;  
16         if (m == 0)
17         {
18             n--;
19         }
20         int len = perCount;
21         for (int i = 0; i <= n; i++)
22         {
23             if(i == n && m != 0)
24             {
25                 len = m;
26             }
27             for(int j = perCount*i; j < perCount*i+len; j++)
28             {
29                 //接口类的方法
30                 dealByGroupCallback.func(j,i,n+1);
31             }
32         }        
33       }
34 }

调用:TestDemo.java

 1 public class TestDemo {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7            final int ss = 0;
 8            DealByGroup dealByGroup = new DealByGroup(100,11,new DealByGroupCallback() {
 9                   public void func(int index,int groupIndex,int totalgroup) {
10                         //这里可以写具体的方法体的话可以调用局部变量ss,也可以将方法体写在另外的函数中,在这里执行。
11                         System.out.println(index + "aaaaaaaaaa" + ss);
12                   }});
13            dealByGroup.deal();
14            DealByGroup dealByGroup2 = new DealByGroup(100,11,new DealByGroupCallback());
15            dealByGroup2.deal();
16     }    
17     
18 
19 }

 --OVER

后记:推测线程的管理也是这种模式。new Thread(<A implements Runnable>)

这两天出于要面试的原因,再次复习设计模式,发现其实这个回调函数的实现,应用了两种设计模式。

其一:策略模式

IDealByGroupCallback :策略的接口

DealByGroupCallback  :策略的实现

DealByGroup :策略的调用者

在这里DealByGroupCallback,这个策略的具体实现是动态的,根据业务的不同,将不同的业务逻辑放到DealByGroupCallback的func中去。这里应用了类的继承来实现策略的动态拓展,

以不变应万变。

其一:门面模式

DealByGroup相当于门面类,将方法的反复调用操作流程都放到一个类中,main作为调用者不需要关注流程怎么实现, 只需要将操作的内容交给DealByGroup。

         

        

原文地址:https://www.cnblogs.com/zhuri/p/2876227.html