使用策略模式(Strategy)实现多关键字排序

“策略模式”的出现,是为了提供一套相互之间可灵活替换的算法,在不影响上层接口的情况下,用户可以自由选择不同的算法完成逻辑。

策略模式的UML示意图如下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

r_image002.jpg 

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype>

 

其中算法的模型接口在“抽象策略”中定义,各具象策略实现不同的策略。“消费 API ”就是调用不同算法的类,在其内部根据不同需要选择不同的算法。有时需要将具象策略实例化后再传给其它类,这时可以使用“简单工厂”( Simple Factory “工厂方法”( Factory Method 生成所需的具象策略。下面就以我正在做的一个项目,简化一下后说明一下策略模式的使用。

该项目是一个小型的商业网站,逻辑层由Servlet实现。用户有一个需求,需要从数据库调出商品信息后能够对记录按名称(name)、规格(standard)、价格(price)和注册日期(register date)进行排序。虽然可以考虑按不同的排序关键字使用不同的sql语句(即不同的order by)查询数据库。但这样做的网络数据流量太大,每次需要从数据库完整地取回一个数据集(ResultSet),所以我选择了将数据集一次取到客户端的一个List中,然后在客户端按不同的关键字对List进行排序。

java.util.Collections类中有一个public static void sort(List list, Comparator comparator)的方法,可以按照不同的Comparator对象对list进行排序,它使用的是快速排序,所以效率非常高。而java.util.Comparator是一个接口:

 

None.gif package java.util;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   abstract   interface  Comparator  dot.gif {
InBlock.gif  boolean equals(Object 
object);
InBlock.gif
InBlock.gif  
int compare(Object object, Object object1);
ExpandedBlockEnd.gif}

None.gif
None.gif

 

其中和排序有关的是compare方法,它返回一个整数,若第一个参数比第二个参数“大”,则返回一个正数,若“小”则返回一个负数,若“相等”则返回0,这里的“大”、“小”、“相等”是由compare方法具体实现定义的一种比较标准。由这个方法不禁想到C语言中qsort函数中使用的函数指针int *compare(*,*)JAVA中之所以没有函数指针,就是用接口取代了(更详细的介绍见《Effective Java》中第22条“用类和接口来代替函数指针”)。

很明显,Comparator接口就是我们的“抽象策略”,sort方法就是我们的“消费API”,而不同的“具象策略”就是我们从Comparator接口实现的根据不同关键字排序的类。

整个排序模型的UML图如下,其中为了作图方便,我从Comparator继承了一个接口ItemComparator,根据不同的关键字从ItemComparator接口泛化了NameComparator类,PriceComparator类,RegisterDateComparator类和StandardComparator类。实际运用中不需要这个接口,四个类可以直接从Comparator泛化。ItemBean是一个封装了商品信息的beanList中存放的就是这些beanItemSortItemComparator以及四个具体类实现了“简单工厂”模式,并封装了sort方法。

 o_strategy.dfPackage.jpg

 


    下面是具体的代码(

StandardComparator 类的代码与 NameComparator 类的代码大同小异,在这里不列出):

 

NameComparator类:

 

None.gif package com.lim.designpatterns.strategy;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  NameComparator implements ItemComparator dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif  NameComparator()
dot.gif{}  // 将构造器封装,包外的类欲得到Comparator实例只能通过简单工厂
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif  
public int compare(Object o1,Object o2)dot.gif{
InBlock.gif    String name1
=((ItemBean)o1).getName();
InBlock.gif    String name2
=((ItemBean)o2).getName();
InBlock.gif
InBlock.gif    
return name1.compareTo(name2);  // 调用String的CompareTo方法
ExpandedSubBlockEnd.gif
  }

ExpandedBlockEnd.gif}

None.gif

 

PriceComparator

 

None.gif package com.lim.designpatterns.strategy;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  PriceComparator implements ItemComparator dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif  PriceComparator()
dot.gif{}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public int compare(Object o1,Object o2)dot.gif{
InBlock.gif    Double price1
=new Double(((ItemBean)o1).getPrice());
InBlock.gif    Double price2
=new Double(((ItemBean)o2).getPrice());
InBlock.gif
InBlock.gif    
return price1.compareTo(price2);  // 调用Double的CompareTo方法
ExpandedSubBlockEnd.gif
  }

ExpandedBlockEnd.gif}

 

RegisterDateComparator

 

None.gif package com.lim.designpatterns.strategy;
None.gif
None.gifimport java.util.
* ;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  RegisterDateComparator implements ItemComparator dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif  RegisterDateComparator()
dot.gif{}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public int compare(Object o1,Object o2)dot.gif{
InBlock.gif    Date date1
=((ItemBean)o1).getRegisterDate();
InBlock.gif    Date date2
=((ItemBean)o2).getRegisterDate();
InBlock.gif
InBlock.gif    
return date1.compareTo(date2);  // 调用Date的CompareTo方法
ExpandedSubBlockEnd.gif
  }

ExpandedBlockEnd.gif}

 

ItemSort

 

None.gif package com.lim.designpatterns.strategy;
None.gif
None.gifimport java.util.
* ;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  ItemSort dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public static List sort(List items,ItemComparator c)dot.gif{
InBlock.gif    Collections.sort(items,c);
InBlock.gif    
return items;
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public static final ItemComparator NAME=new NameComparator();  // 简单工厂
InBlock.gif

InBlock.gif  
public static final ItemComparator PRICE=new PriceComparator();
InBlock.gif
InBlock.gif  
public static final ItemComparator STANDARD=new StandardComparator();
InBlock.gif
InBlock.gif  
public static final ItemComparator REG_DATE=new RegisterDateComparator();
ExpandedBlockEnd.gif}

 

TestItemSort

 

None.gif package com.lim.designpatterns.strategy;
None.gif
None.gifimport java.util.
* ;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  TestItemSort dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public static void main(String[] args)dot.gif{
InBlock.gif    List items
=new ArrayList();
InBlock.gif    
// 向List添加条目
InBlock.gif

InBlock.gif    items
=ItemSort.sort(items,ItemSort.NAME);  // 按名称排序
InBlock.gif

InBlock.gif    items
=ItemSort.sort(items,ItemSort.PRICE);  // 按价格排序
InBlock.gif

InBlock.gif    items
=ItemSort.sort(items,ItemSort.REG_DATE);  // 按注册日期排序
InBlock.gif

InBlock.gif    items
=ItemSort.sort(items,ItemSort.STANDARD);  // 按规格排序
ExpandedSubBlockEnd.gif
  }

ExpandedBlockEnd.gif}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值