策略模式把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则由具体的策略类实现。由于算法和环境独立开来,算法的增减,修改都不会影响环境和客户端。策略模式的简易UML图例如下
而使用AspectJ实现的策略模式UML图与之有很大的区别
Context和Strategy接口都由抽象方面StrategyProtocol声明,而具体的策略实现方面负责为具体策略类和环境类分别声明实现接口,并定义了pointcut
discountStrategy用于捕捉特定算法的调用。该方面使用around advice实现对不同策略类的调用。下面就介绍实现的代码
StrategyProtocol抽象方面
public abstract aspect StrategyProtocol {
protected interface Context{}
protected interface Strategy{}
private Strategy Context.strategy=null;
public void Context.setStrategy(Strategy strategy){
this.strategy=strategy;
}
public Strategy Context.getStrategy(){ return strategy;}
}
该方面使用Inter-type声明定义了Context和Strategy接口并为Context接口声明了管理策略类方法。
DiscountStrategyAspect.java
public aspect DiscountStrategyAspect extends StrategyProtocol{
declare parents : Discount implements Context;//Discount为具体的环境类
//定义了三种折扣算法,实现Strategy接口
declare parents : NoDiscountStrategy implements Strategy;
declare parents : FlatRateStrategy implements Strategy;
declare parents : PercentageStrategy implements Strategy;
pointcut discountStrategy(Context context) : target(context)
&& call(double Discount.getDiscount());
//捕捉算法调用联结点(JoinPoint)
double around(Context context) : discountStrategy(context){
Strategy strategy = ((Discount)context).getStrategy();//抽象方面为Context定义的方法
return getDiscount(strategy);
}
//调用特定的策略算法
private double getDiscount(Strategy strategy){
if(strategy instanceof NoDiscountStrategy)
return ((NoDiscountStrategy)strategy).calculateDiscount();
else if(strategy instanceof FlatRateStrategy)
return ((FlatRateStrategy) strategy).calculateDiscount();
else if(strategy instanceof PercentageStrategy)
return ((PercentageStrategy)strategy).calculateDiscount();
else
throw new RuntimeException("No such strategy defined");
}
}
Discount.java环境类
public class Discount{//没有实现getDiscount方法,由具体策略方面实现
public double getDiscount(){
return 0;
}
}
NoDiscountStrategy.java策略类
public class NoDiscountStrategy{
private double price;
private int copies;
public NoDiscountStrategy(double price,int copies){
this.price=price;
this.copies=copies;
}
public double calculateDiscount(){
return 0;
}
}
FlatRateStrategy.java策略类
public class FlatRateStrategy{
private double price;
private int copies;
private double amount;
public FlatRateStrategy(double price,int copies,double amount){
this.price=price;
this.copies=copies;
this.amount=amount;
}
public double calculateDiscount(){
return amount*copies;
}
}
PercentageStrategy.java策略类
public class PercentageStrategy{
private double price;
private int copies;
private double percentage;
public PercentageStrategy(double price,int copies,double percentage){
this.price=price;
this.copies=copies;
this.percentage=percentage;
}
public double calculateDiscount(){
return copies*price*percentage;
}
}
以上三个策略类都有calculateDiscount方法,该方法实现不同的折扣策略
Demo.java测试代码
public class Demo {
public static void main(String[] args) {
double price=100;
int copies=10;
Discount discount=new Discount();
discount.setStrategy(new NoDiscountStrategy(price,copies));
System.out.println("Discount using No Discount Strategy is:"+discount.getDiscount());
discount.setStrategy(new FlatRateStrategy(price,copies,20));
System.out.println("Discount using Flat Rate 20 Discount Strategy
is:" +discount.getDiscount());
discount.setStrategy(new PercentageStrategy(price,copies,0.5));
System.out.println("Discount using Percentage 50% Strategy
is:" +discount.getDiscount());
}
}
测试代码分别让环境类Discount使用了三个策略类并返回折扣值。其结果如下
Discount using No Discount Strategy is:0.0
Discount using Flat Rate 20 Discount Strategy is:200.0
Discount using Percentage 50% Strategy is:500.0
至此,我已经使用AspectJ完全实现了一个使用策略模式设计的折扣例子。本系列的下一篇文章将介绍如何用AspectJ实现工厂方法模式。(说明一点,本系列文章假设读者熟悉设计模式和AspectJ,所以不会过多介绍这方面的知识,主要是以示例为主,所有的例子都通过测试可以运行,因本人首次发表文章如有不足和错误还请各位多多原谅)。
|