定义:定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换,策略模式使得算法的变化可独立于使用它的客户。
类图:
说明:Context表示环境类,它通过ConcreteStrategy对象配置其执行环境,并维护一个对Strategy的引用实例,可以定义一个接口Strategy存取其数据;Strategy表示抽象策略类,它定义一个公共的接口给所有支持的算法,Context可以使用这个接口调用ConcreteStrategy定义的算法;ConcreteStrategyA和ConcreteStrategyB表示具体策略类,它们实现Strategy接口定义的算法。
优点:
①.提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活的增加新的算法或行为
②.提供了管理相关的算法的办法
③.提供了一种可以替换继承关系的办法
④.可以避免多重条件选择语句
⑤.提供了一种算法的复用机制,不同的环境类可以方便地复用策略类。
缺点:
①.客户端必须知道所有的策略类,并自行决定使用哪一个策略类
②.将造成系统产生很多具体策略类
③.无法同时在客户端使用多个策略类
适用环境:
①.一个系统需要动态地在几种算法中选择一种
②.避免使用难以维护的多重条件选择语句
③.不希望客户端知道复杂的、与算法相关的数据结构,提高算法的保密性与安全性。
实例场景:策略模式实例值电影票打折,某电影院售票系统为不同类型的用户提供了不同的打折方式(Discount),学生凭学生证可享受8折优惠(StudentDiscount),儿童可享受减免10元的优惠(ChildrenDiscount),VIP用户处享受半价优惠外还可以进行积分(VIPDiscount)。
实例类图:
实例代码:
/**
* 折扣类:抽象策略类
* @author fly
*
*/
public interface Discount{
public double calculate(double price);
}
/**
* 学生折扣价:具体策略类
* @author fly
*
*/
public class StudentDiscount implements Discount{
@Override
public double calculate(double price) {
// TODO Auto-generated method stub
return price*0.8;
}
}
/**
* 儿童折扣价:具体策略类
* @author fly
*
*/
public class ChildrenDiscount implements Discount{
@Override
public double calculate(double price) {
// TODO Auto-generated method stub
return price-10;
}
}
/**
* VIP会员折扣类:具体策略类
* @author fly
*
*/
public class VIPDiscount implements Discount{
@Override
public double calculate(double price) {
// TODO Auto-generated method stub
System.out.println("增加积分");
return price*0.5;
}
}
//电影票类:环境类
/**
* 电影票类:环境类
*
* @author fly
*
*/
class MovieTicket {
private double price;
private Discount discount;
public double getPrice() {
return discount.calculate(price);
}
public void setPrice(double price) {
this.price = price;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
}
//客户端测试类:
public class Client {
public static void main(String[] args) {
MovieTicket mt = new MovieTicket();
mt.setPrice(50.00);
double currentPrice;
Discount obj;
obj = new StudentDiscount();//可以通过配置文件实现
mt.setDiscount(obj);
currentPrice = mt.getPrice();
System.out.println("折后价为:"+currentPrice);
System.out.println("-----------------------------------------");
obj = new VIPDiscount();
mt.setDiscount(obj);
currentPrice = mt.getPrice();
System.out.println("折后价为:"+currentPrice);
}
}
//运行结果: