您的位置:首页 > 编程语言 > Java开发

java设计模式(2)策略模式

2016-07-05 13:40 225 查看

策略模式

  策略模式也是常用的设计模式之一,属于对象的行为模式。其定义为:针对一组算法,将算法封装到具有共同接口的独立类中,从而使它们可以互换。此模式让算法的变化独立于使用算法的客户。

   举个例子,超市要打折促销一批苹果。有半价折扣,有满减折扣,有88折有66折等等不同形式的促销方案,该超市可能这周用半价的方案,下周生意好了可能用88折,过些时也可能用满减。并且今后也可能添加更多方案。这时如何设计出可复用、可扩充、可维护的一组类来表达这种情景呢?

   根据策略模式的定义,我们可以把这些打折方法看做一组策略(或算法),将这些算法抽象到一个有打折方法的接口中。每个打折方法都是一个实现了此打折方法的类。代码如下:

/**
* 算法的抽象接口
*/
public interface Strategy{
//打折方法
double disCount(int price);
}

/**
*方法A :8折
*/
public class StrategyA implements Strategy{
@Override
public double disCount(int price){
return price*0.8;
}
}
/**
*方法B :满100后,多出部分半价
*/
public class StrategyB implements Strategy{
@Override
public double disCount(int price){
return price<100?price:(price-100)*0.5+100;
}
}
/**
*方法C :优惠50
*/
public class StrategyC implements Strategy{
@Override
public double disCount(int price){
return price-50;
}
}


  以上代码将每种打折促销方法都写成一个类,并拥有统一的父接口。所有实现了策略接口的类在该模式下都称为“具体策略类“,该接口为“抽象策略类”。目标是要实现苹果的不同折扣方案,苹果类又称为“环境角色类“。

public class Apple{  //模拟苹果,在策略模式中此类为“环境角色类”
public Apple(){}
public Apple(Strategy strategy){
this.strategy=strategy; //通过构造函数给策略实例赋值
}
private double price; //价格
private Strategy strategy; //保存该策略接口引用
public void setPrice(double price){
this.price=price;
}
public double getPrice(){
return price;
}
public double calculatePrice(){
return strategy.disCount(price);
}
}

public class Test{
public static void main(String []args){
Strategy strategy = new StrategyA(); //在这里更换具体策略
//Strategy strategy = new StrategyB();
//Strategy strategy = new StrategyC();
Apple apple = new Apple(strategy);
apple.setPrice(200);
int discount = apple.calculatePrice();
System.out.println("折扣后价格:"+discount);
}
}


  在环境角色类中嵌入抽象的策略接口,以便在应用中动态改变所需的打折策略。上面例子中嵌入方式为:在环境角色类中保存一个抽象策略类的变量,在构造函数中为其赋值,当然,也可以直接在折扣方法的参数列表中拥有一个嵌入抽象策略类引用,等到调用该方法时再赋值。如下:

public class Apple{

private double price; //价格

public void setPrice(double price){
this.price=price;
}
public double getPrice(){
return price;
}
public double calculatePrice(){
return price;
}
public double calculatePrice(Strategy strategy){
return strategy.disCount(price);
}
}
public class Test{
public static void main(String []args){

Apple apple = new Apple();
apple.setPrice(200);
int discount = apple.calculatePrice(new StrategyA());//在这里更换折扣策略
System.out.println("折扣后价格:"+discount);
}
}


  本人更倾向于使用第二种方式实现策略模式,因其耦合性更低,不用嵌入策略类的变量,不用在构造函数中耦合策略类。在Java API中,关于File类的list()方法(返回该File类底下的文件名或目录名的集组成的数组)即使用了策略模式。list方法有2个版本,如下:

public String[] list(); //没有参数,返回该目录下所有文件名组成的String数组

public String[] list(FilenameFilter filter); //有一个过滤器的参数,FilenameFilter 是一个接口

  带参数的list方法返回经过滤器筛选后的数组,FilenameFilter 相当于策略模式中的抽象策略,该接口含有一个选择文件名的方法定义,任何一个实现此接口的类充当此参数,实现自己的过滤效果。FilenameFilter 接口如下:

public interface FilenameFilter {
boolean accept(File dir, String name);
}


实现具体的过滤策略

public static void main(String[]args){
File file = new File(".");//将当前目录赋值给file
//String []list = file.list(filter); filter应当是一个实现了FilenameFilter 接口的类的实例,这里使用匿名内部类实现,如下
String[] list = path.list(new FilenameFilter() {
//筛选文件名含有“Hello”的java文件
public boolean accept(File f, String name) {
return Pattern.matches("\S*Hello\S*\.java",name);
}
});
}


关于java的策略模式就讲到这里了,若有不正确的地方还请各位网友指正,联系方式:wthfeng@126.com。

参考文章:

1. 《Head First 设计模式》

2. http://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java设计模式