在很多情况下,实现某个目标的途径不止一条,例如在外出旅游时游客可以选择多种不同的出行方式,如骑自行车、坐汽车、坐火车、坐飞机,根据实际情况选择最合适的一种出行方式。
定义
定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户而变化。
结构
Context(环境类)
环境类是使用算法的角色,它在解决某个问题时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
Strategy(抽象策略类)
抽象策略类为所支持的算法声明抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
ConcreteStrategy(具体策略类)
具体策略类实现了再抽象策略类中声明的算法,在运行时具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务功能。
实现
// 环境类 - 电影票类
public class MovieTicket {
private double price;
private Discount discount;
public void setPrice(double price) {
this.price = price;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double getPrice() {
return discount.calculate(price);
}
}
// 抽象策略类 - 折扣类
public interface Discount {
double calculate(double price);
}
// 具体策略类 - 学生票价
public class StudentDiscount implements Discount {
private double discount = 0.8;
@Override
public double calculate(double price) {
System.out.println("学生票:");
return price * discount;
}
}
// 具体策略类 - 儿童票
class ChildrenDiscount implements Discount{
private double discount = 10;
@Override
public double calculate(double price) {
System.out.println("儿童票:");
if(price >= 20) {
return price - discount;
}else {
return price;
}
}
}
优点
1、策略模式提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法和行为。
2、提供了管理相关的算法族的办法。
3、可以避免多重条件选择语句,多重选择语句不易维护。
4、提供了一种算法的复用机制。
缺点
1、无法在客户端使用多个策略类,每次只能使用一个策略类,无法在使用完一个策略类之后再使用另一个策略类完成剩余功能的情况。
2、会造成系统产生很多具体策略类,任何细小的变化将导致系统要增加一个新的策略类。