背景:在项目中因为牵涉到大数据的处理,需要经常在各个类中用到分组的模式。同样地流程控制代码,到处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。