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

本文介绍策略模式的概念及其在Java中的应用。策略模式允许在运行时选择算法或行为,通过定义一系列可互换的算法来实现。文章详细展示了如何利用策略模式实现超市打折促销策略的灵活配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

策略模式

  策略模式也是常用的设计模式之一,属于对象的行为模式。其定义为:针对一组算法,将算法封装到具有共同接口的独立类中,从而使它们可以互换。此模式让算法的变化独立于使用算法的客户。
   举个例子,超市要打折促销一批苹果。有半价折扣,有满减折扣,有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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值